Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Ms Jewish Anime
Feb 18, 2007


WATCH THE WAY "THE JEW" DODGES AND WEAVES LIKE A SNAKE IT IS SADLY ALL HE KNOWS
I have a question about fflush(stdin) in C programming.
It's supposed to clear some input buffer that holds input data. However I have yet to come across a situation that requires fflush for stdin. If possible, could someone explain a situation or give an example when fflush(stdin) or even stdout would be required?

Adbot
ADBOT LOVES YOU

Plastic Jesus
Aug 26, 2006

I'm cranky most of the time.

Bush is a QT posted:

I have a question about fflush(stdin) in C programming.
It's supposed to clear some input buffer that holds input data. However I have yet to come across a situation that requires fflush for stdin. If possible, could someone explain a situation or give an example when fflush(stdin) or even stdout would be required?

Always flush shared file handles in multi-threaded applications. I can't for the life of my think of a time when multiple threads would be accessing stdin, but it happens all the time with stdout. If you have several threads that all want to print poo poo to the screen you have to make them stand in line to do so or they'll end up printing over the top of each other. So you make them acquire a mutex, then write to stdout. You want to flush stdout at that point to ensure that everything has been written before you release the mutex.

Fake edit: just thought of when you'd want to fflush(stdin)- when your application will be used in a pipe, e.g. 'cat somefile|yourapp'.

Ms Jewish Anime
Feb 18, 2007


WATCH THE WAY "THE JEW" DODGES AND WEAVES LIKE A SNAKE IT IS SADLY ALL HE KNOWS
thank you

Vanadium
Jan 8, 2005

I am pretty sure that fflushing input streams does not do anything.

POKEMAN SAM
Jul 8, 2004

Vanadium posted:

I am pretty sure that fflushing input streams does not do anything.

From the man page:

code:
Flushing  an  input  stream  discards any buffered input and
adjusts the file pointer such that the next input  operation
accesses  the  byte  after  the  last one read.

FigBug
Apr 27, 2002

Lemon Party - Lest we Forget

Ugg boots posted:

code:
Flushing  an  input  stream  discards any buffered input and
adjusts the file pointer such that the next input  operation
accesses  the  byte  after  the  last one read.

fflush(stdin) is undefined behavior in ANSI C. Some compilers implement it, some don't.

Vanadium
Jan 8, 2005

Ugg boots posted:

From the man page:

code:
Flushing  an  input  stream  discards any buffered input and
adjusts the file pointer such that the next input  operation
accesses  the  byte  after  the  last one read.

It does not say that in my manpage. Are you sure you are not missing some "conforming to" part?

haveblue
Aug 15, 2005



Toilet Rascal
The OS X 10.5 manpage for fflush makes no mention of input streams; it only says the function will fail if the stream is "not open for writing".

6174
Dec 4, 2004
I've got a template function in which I'm doing a comparison like:

code:
if (number < 0) {
    number *= -1;
}
number is of type T. When T is an unsigned type the compiler gives me a warning:

../shared/number_stuff.h:102: warning: comparison of unsigned expression < 0 is always false

Is there anyway I can reasonably make these warnings go away? I tried enclosing it in an if (numeric_limits<T>::is_signed) block, but the compiler still complains.

more falafel please
Feb 26, 2005

forums poster

6174 posted:

I've got a template function in which I'm doing a comparison like:

code:
if (number < 0) {
    number *= -1;
}
number is of type T. When T is an unsigned type the compiler gives me a warning:

../shared/number_stuff.h:102: warning: comparison of unsigned expression < 0 is always false

Is there anyway I can reasonably make these warnings go away? I tried enclosing it in an if (numeric_limits<T>::is_signed) block, but the compiler still complains.

Since numeric_limits<T>::is_signed is a compile-time constant, you should be able to make use of SFINAE to make one specialization for signed types and another for unsigned types. Otherwise, you can just turn off that warning with a #pragma around that block or for that file on the command line, but I'm pretty sure SFINAE is the proper way to do it. Concepts would make this easier.

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.
Try boost::enable_if

chris_bacon
Feb 27, 2008
Is it possible to use a struct or class in a templated function? I've already made a working, templated, double-linked list and now I'm trying to use it in a call center simulation.

I made the struct:

code:
struct caller_t {
  public: 
    string          status; 
    string          name;
    int           timestamp;
    int		  duration;
};
and I'm trying to insert a struct into my double-linked list, so I made a dynamic array of the caller_t struct.

When I compile, I get this:

code:
cse1695p58% g++ -Wall -Werror -o call call.cpp
call.cpp:38:32: error: character constant too long for its type
call.cpp:42:32: error: multi-character character constant
call.cpp:46:32: error: character constant too long for its type
call.cpp:50:32: error: multi-character character constant
call.cpp: In function ‘int main()’:
call.cpp:38: error: no match for ‘operator==’ in ‘(((caller_t*)(((long unsigned int)i) * 24ul)) + callers)->caller_t::status == 1768846701’
call.cpp:39: error: no matching function for call to ‘Dlist<caller_t>::insertFront(caller_t&)’
dlist.cpp:14: note: candidates are: void Dlist<T>::insertFront(T*) [with T = caller_t]
call.cpp:42: error: no match for ‘operator==’ in ‘(((caller_t*)(((long unsigned int)i) * 24ul)) + callers)->caller_t::status == 1735355492’
call.cpp:43: error: no matching function for call to ‘Dlist<caller_t>::insertFront(caller_t&)’
dlist.cpp:14: note: candidates are: void Dlist<T>::insertFront(T*) [with T = caller_t]
call.cpp:46: error: no match for ‘operator==’ in ‘(((caller_t*)(((long unsigned int)i) * 24ul)) + callers)->caller_t::status == 1819698546’
call.cpp:47: error: no matching function for call to ‘Dlist<caller_t>::insertFront(caller_t&)’
dlist.cpp:14: note: candidates are: void Dlist<T>::insertFront(T*) [with T = caller_t]
call.cpp:50: error: no match for ‘operator==’ in ‘(((caller_t*)(((long unsigned int)i) * 24ul)) + callers)->caller_t::status == 1852796517’
call.cpp:51: error: no matching function for call to ‘Dlist<caller_t>::insertFront(caller_t&)’
dlist.cpp:14: note: candidates are: void Dlist<T>::insertFront(T*) [with T = caller_t]
call.cpp:60: error: request for member ‘name’ in ‘curcaller’, which is of non-class type ‘caller_t*’
call.cpp:61: error: request for member ‘duration’ in ‘curcaller’, which is of non-class type ‘caller_t*’
Here's my insertFront for reference:

code:
template <class T>
void Dlist<T>::insertFront(T *o)
{
  node *np = new node;
  np->next = first;
  np->o = o;
  if (isEmpty()) {
    last = np;
  } 
  else {
    first->prev = np;
  }
  first = np;
}
Am I using incorrect syntax or is it not possible to do?

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh
You can use objects in templates, that's the point. You're trying to call insertFront with a reference as the parameter and not a pointer. The types need to match up.

lhunc
Jan 4, 2007
I'm trying to get myself back into C but things are going a bit slow...

fwrite requires a pointer to a string as the first argument so how would I properly cast a character constant to a pointer? ie:

// Wrong
fwrite('\n', sizeof(char), 1, fd);

// Wrong
fwrite((char *) '\n', sizeof(char), 1, fd);

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh
Don't bother with casts, just do fwrite("\n",1,1,fd);

Standish
May 21, 2001

lhunc posted:

I'm trying to get myself back into C but things are going a bit slow...

fwrite requires a pointer to a string as the first argument so how would I properly cast a character constant to a pointer? ie:

// Wrong
fwrite('\n', sizeof(char), 1, fd);

// Wrong
fwrite((char *) '\n', sizeof(char), 1, fd);
You cannot take the address of a literal so you'll have to assign it to a variable:
code:
char c = '\n';
fwrite(&c, sizeof(char), 1, fd);
Although it's probably simpler just to write a string consisting of a single character, like the other guy said.

lhunc
Jan 4, 2007
thanks guys, guess I'm just over thinking it.

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh
Oh, I forgot to mention, another option would be to use fputc('\n',fd); if you're only writing single characters.

POKEMAN SAM
Jul 8, 2004

HB posted:

The OS X 10.5 manpage for fflush makes no mention of input streams; it only says the function will fail if the stream is "not open for writing".

I found it on this site http://www.hmug.org/man/3/fflush.php but I guess that's only for ISO C90?

The Red Baron
Jan 10, 2005

I'm wondering if it's at all possible to further specialize a nested class of a base class in its subclass(es)?

What I want is something that works theoretically like this (ignore the actual types used, they're not important):
code:
struct base
{
  template <typename T>
  struct x;

  template <>
  struct x<float>
  {
    typedef float some_type;
  };

  // (More specializations...)
};

struct derived : base
{
  using base::x;

  template <>
  struct x<int>
  {
    typedef int some_type;
  };
};
which isn't allowed, at least not in MSVC++ 2008. My hope was that I can somehow keep most of the general code in a base class and that doing derived::x<int>::some_type and derived::x<float>::some_type will give the specialized results. I hope I managed to pose this question in an understandable way :shobon:

That Turkey Story
Mar 30, 2003

The Red Baron posted:

I'm wondering if it's at all possible to further specialize a nested class of a base class in its subclass(es)?

What I want is something that works theoretically like this (ignore the actual types used, they're not important):

Not in standard C++, however the VC++ compilers have a little hacky way to make it work which is actually what is used to provide VC++ with native support for Boost.Typeof.

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh
Even if it did work, wouldn't you end up indirectly specializing base::x instead of making a specialized version just for derived::x? Also, I'm pretty sure explicit specializations aren't allowed inside a class.

The following is probably closer to what you want (compiles under GCC, Comeau, and VC++2005):
code:
struct base
{
	template <typename T>
	struct x;
};

template <>
struct base::x<float>
{
	typedef float some_type;
};

struct derived : base
{
	template<typename T>
	struct x : base::x<T>
	{};
};

template <>
struct derived::x<int>
{
	typedef int some_type;
};

int main()
{
	derived::x<int>::some_type i;
}

The Red Baron
Jan 10, 2005

Avenging Dentist posted:

Even if it did work, wouldn't you end up indirectly specializing base::x instead of making a specialized version just for derived::x?

Quite possible. Hadn't thought about that, to be honest.

quote:

The following is probably closer to what you want (compiles under GCC, Comeau, and VC++2005):
That seems like a far better approach, I'll give it a try. Many thanks to you both! :)

6174
Dec 4, 2004
I've got a C program that I've got to insert some sorting operations into. I've got several arrays, say a, b, and c. I need to sort a into non-decreasing order, however the order of b and c must change in the same manner as a does. This is easy enough to do by swapping the elements of b and c in the same manner as a when sorting a. The problem comes into when later I've got a similar situation with arrays x and y. I don't want to have to be coding up 4-5 slight variants of the same sorting algorithm (and the number of "dependent" arrays varies from 1 to 4). How can I reasonably make only one sorting algorithm deal with this situation? Would a function pointer to a swap routine be reasonable? If needed I can restructure things to make this easier.

lhunc
Jan 4, 2007
Another C newb question, this time regarding the passing of structures to functions.

I've got a structure like this:
code:
struct note {
    time_t creation_date;
    int priority;
    int *note_text;
} notes[100];
and then a function which takes an array of note structures, which I'm sure is wrong...
code:
void get_notes(note *some_notes);
The compiler (gcc) is giving me an error (at the function declaration line):
code:
error: expected ')' before '*' token
Can anyone point me in the right direction?

haveblue
Aug 15, 2005



Toilet Rascal

6174 posted:

Would a function pointer to a swap routine be reasonable? If needed I can restructure things to make this easier.

This would be quite reasonable. You'd have the indices as its parameters and just have it perform the same swap on any of an arbitrary set of arrays.

quote:

Can anyone point me in the right direction?

You need the struct keyword before the type of the parameter (or a typedef statement for the structure definition).

haveblue fucked around with this message at 22:24 on Apr 14, 2008

6174
Dec 4, 2004

HB posted:

This would be quite reasonable. You'd have the indices as its parameters and just have it perform the same swap on any of an arbitrary set of arrays.

That is what I figured, I just wanted to make sure I wasn't missing something stupid.

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh

lhunc posted:

Another C newb question, this time regarding the passing of structures to functions.

..

Can anyone point me in the right direction?

If you're doing pure C, you need either struct note in place of note, or the following:

code:
typedef struct { /* ... */ } note;
note notes[1000];

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

lhunc posted:

Another C newb question, this time regarding the passing of structures to functions.

I've got a structure like this:
code:
struct note {
    time_t creation_date;
    int priority;
    int *note_text;
} notes[100];

As a general principle, you're probably better off splitting this into a declaration of a struct type, and a declaration of an array of that type.

code:
struct note { ... };
struct note notes[100];
It's just less confusing that way.

quote:

and then a function which takes an array of note structures, which I'm sure is wrong...
code:
void get_notes(note *some_notes);

This is one of the areas where C and C++ differ. In C, it's

code:
void get_notes(struct note *some_notes);
You use struct note { ... }; to declare a structure, and just struct note to use it.

Since this is really annoying, generally you take that structure and typedef it to an easier name.

code:
struct note_struct { ... };
typedef note_struct note;
note notes[100];

void get_notes(note *some_notes);
Since the "struct and then typedef" idiom is so common, people usually combine it into one block, like you did with the array declaration - which is why you shouldn't do that with array declarations, because at a quick glance people will assume it's a typedef. (I was mighty confused for about 10 seconds why you were naming your note type "notes[100]".)

code:
typedef struct note_struct { ... } note;
note notes[100];

void get_notes(note *some_notes);
EDIT: oh yeah, you can just cut the word note_struct completely, create an anonymous struct, and then typedef it to the name "note". Been so long since I did C that I forgot that.

code:
typedef struct { ... } note;
note notes[100];

void get_notes(note *some_notes);

lhunc
Jan 4, 2007

Avenging Dentist posted:

If you're doing pure C, you need either struct note in place of note, or the following:

code:
typedef struct { /* ... */ } note;
note notes[1000];

Thanks, I've modified it to read:

code:
typedef struct {
   /*...*/
} note;

note notes[100];
However, I'm still getting an error at the function declaration line [void get_notes(note *notes)];
code:
error: expected ‘)’ before ‘*’ token
Any ideas?

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh
Could you just post your code on https://www.pastebin.com or something?

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.
Did you declare that struct in a header file? Are you sure you're not including an older version of the header or something?

lhunc
Jan 4, 2007
edit: thanks guys, I got it - I had the structures defined after the function prototypes, switching them did the trick.

lhunc fucked around with this message at 02:22 on Apr 15, 2008

almostkorean
Jul 9, 2001
eeeeeeeee
Can someone tell me why this doesn't work?

code:
 
  char operand;
  double *number;
  *number = atof( operand );
When I compile I get:
code:
calc.cpp:31: error: invalid conversion from ‘char’ to ‘const char*’
calc.cpp:31: error:   initializing argument 1 of ‘double atof(const char*)’
calc.cpp:31: error: cannot convert ‘double’ to ‘double*’ in assignment
I feel like this should work, but I can't figure it out.

haveblue
Aug 15, 2005



Toilet Rascal

almostkorean posted:

Can someone tell me why this doesn't work?

code:
 
  char operand;
  double *number;
  *number = atof( operand );
When I compile I get:
code:
calc.cpp:31: error: invalid conversion from ‘char’ to ‘const char*’
calc.cpp:31: error:   initializing argument 1 of ‘double atof(const char*)’
calc.cpp:31: error: cannot convert ‘double’ to ‘double*’ in assignment
I feel like this should work, but I can't figure it out.

Well, first, atof expects a string, not a single char (and it expects a null terminator, so don't just pass it &operand).

Second, once you get it to run, it's going to crash because you didn't allocate any memory for number to point to.

Lexical Unit
Sep 16, 2003

atof takes a const char*, you're giving it a char.

Beaten of course, I meant to hit preview and not post.

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh
operand is a single character and should be a char*. I'm not sure why you're using atof to parse a single character though...

Also, you aren't allocating any memory for *number.

EDIT: haha

Zombywuf
Mar 29, 2008

almostkorean posted:

Can someone tell me why this doesn't work?

code:
 
  char operand;
  double *number;
  *number = atof( operand );

operand is a char, atof takes a char *. You want something more like char operand[] = "123";.

Steampunk Mario
Aug 12, 2004

DIAGNOSIS ACQUIRED
:eng101: Also, operand is uninitialized and therefore this snippet won't do anything useful (and may possibly have undefined behavior).

Adbot
ADBOT LOVES YOU

Lexical Unit
Sep 16, 2003

Hopefully that's just a dumbed down snippet of code and the real code allocates memory to number and populates operand... at least, that's what I assumed.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply