Warning with sscanf format - c

I've been getting the following warning when trying to write a program that only allows strings of numbers:
warning: format ‘%s’ expects argument of type char *’, but argument 3 has type ‘char (*)[100]’
Why am I getting this warning, and what does it mean/consequences? Not had any problems running the code.
The program:
char check[100];
char line[100];
int i;
int true = 0;
int main
{
fgets(line, sizeof(line), stdin);
sscanf(line, "%s" , &check);
for(i=0; i<3; i++)
{
if(isdigit(check[i]) == 0)
{
true++;
}
else
continue;
}
if(true>0)
printf("Not a number.\n");
else
printf("Is a number.\n");
return(0);
}

The compiler is complaining about the use of &check in the following line.
sscanf(line, "%s" , &check);
The expected argument is just check.
sscanf(line, "%s" , check);

Related

Console warning if statement not working

#include <stdio.h>
#include <stdlib.h>
#include<string.h>
int main()
{
char buffer[1024];
printf("Hello\n");
printf("What would you like to search\n");
printf("Here are the options\n");
printf("s : How are you\n");
printf("c : What would you like to search\n");
scanf("%s",&buffer);
if(buffer == 's')
printf("iam fine\n");
else if (buffer == 'c')
printf("What would you like to search\n");
fgets(buffer, sizeof buffer, stdin);
system(buffer);
return 0;
}
Console Errors(program not functioning correctly)
C:\Users\sc\Documents\ForumCode\test\foo.c|12|warning: format '%s' expects type 'char *', but argument 2 has type 'char (*)[1024]'|
C:\Users\sc\Documents\ForumCode\test\foo.c|13|warning: comparison between pointer and integer|
C:\Users\sc\Documents\ForumCode\test\foo.c|15|warning: comparison between pointer and integer|
||=== Build finished: 0 errors, 3 warnings ===|
It should be scanf("%s",buffer)
Your buffer variable is an array of characters, but in your if statement, you're trying to compare this array to a single character.
Perhaps what you're looking for is if (buffer[0] == 's')

Error on the format

11: warning: format ‘%s’ expects type ‘char *’, but argument 2 has type ‘char (*)[100]’
This is my error....Cant fix it...
#include <stdio.h>
#include <string.h>
int main()
{
char *a;
char *count;
char str[100];
int i ;
printf("\n:enter string for Palindrome test\t");
scanf("%s", &str);
i= strlen(str);
//a=(char *)malloc(i*sizeof(char));
a=&str[0];
count=&str[i-1];
while((*(a++)==*(count--)) && i>=1)
{ i--; }
if(i==0) { printf("\n%s is a palin",str);}
else { printf("\n%s is not palin",str);}
}
Sure you can fix it. Just don't pass the wrong type. Change:
scanf("%s", &str);
To:
scanf("%s", str);
Or, equivalently:
scanf("%s", &str[0]);
You don't always use an ampersand passing arguments to scanf(). If the format string contains either a %c or a %s, it will be looking for a char* type. When you call it with &str, you are calling it with a char** type, or as the compiler says, a char*[100] (a pointer to an array of 100 chars).

C Programming segfault on scanf

I have written the following code segment and am having trouble understanding why it would not get to the last printf line. I get a segfault immediately after line 4. The kill_char is just used to kill the 'enter' character added in the previous scanf. Any help would be greatly appreciated, thanks!
int remove = 0;
char kill_char = 'a';
printf("Enter the product number to be removed: ");
scanf("%d", &remove);
scanf("%c", &kill_char);
printf("Does not get here");
EDIT:
Full code is as follows, with the error in the removeProduct function
#include <stdio.h>
#include <stdlib.h>
struct product_node {
char *supply_type;
long number;
char *description;
float price;
int quantity_bought;
float retail_price;
int quantity_sold;
struct product_node *next;
};
struct product_node *head;//declaring head out here
//allows the list to be in scope for the functions
/*Function Prototypes*/
void addProduct();
void removeProduct();
void listProduct();
void listSupplierTypes();
void supplierTypeProfit();
void totalProfit();
void addProduct(){
char kill_char = 'a';//used to kill the enter characters
struct product_node *new_node;
new_node = malloc(sizeof(struct product_node));
printf("\nEnter a string for type: ");
scanf( "%s", &(*new_node).supply_type);
scanf("%c", &kill_char);
printf("Enter the product number: ");
scanf("%ld", &(*new_node).number);
scanf("%c", &kill_char);
printf("Enter the description: ");
scanf("%s", &(*new_node).description);
scanf("%c", &kill_char);
printf("Enter the wholesale price: ");
scanf("%f", &(*new_node).price);
scanf("%c", &kill_char);
printf("Enter the quantity bought: ");
scanf("%d", &(*new_node).quantity_bought);
scanf("%c", &kill_char);
printf("Enter the retail price: ");
scanf("%f", &(*new_node).retail_price);
scanf("%c", &kill_char);
printf("Enter the quantity sold: ");
scanf("%d", &(*new_node).quantity_sold);
scanf("%c", &kill_char);
struct product_node *walker;
walker = head;
int can_insert = 1;
while (!(walker == NULL))
{
if (((*walker).number == (*new_node).number) && ((*walker).supply_type == (*new_node).supply_type))
{
can_insert = 0;
}
walker = (*walker).next;
}
if (can_insert==1)
{
(*new_node).next = head;
head = new_node;
printf("Insertion Successful");
}
else
{
printf("\nERROR INSERTING:This product name and number is already in the list\n");
}
free(new_node);
}
void removeProduct(){
int remove = 0;
char kill_char = 'a';
printf("Enter the product number to be removed: ");
scanf("%d", &remove);
scanf("%c", &kill_char);
printf("Does not get here");
struct product_node *walker;
struct product_node *prev;
prev = head;
walker = (*head).next;
if ((*prev).number == remove)
{
head = walker;
}//points head to second node to remove first
while (!(walker = NULL))
{
if ((*walker).number == remove)
{
(*prev).next = (*walker).next;
}
}
}
void listProduct(){
printf("Still unsure what defines a supplier...");
}
void listSupplierTypes(){
printf("Same as above");
}
void supplierTypeProfit(){
printf("Again");
}
void totalProfit(){
float total = 0.0;
struct product_node *walker;
walker = head;
while(!(walker == NULL))
{
total += ((float)(*walker).quantity_sold * (*walker).retail_price) - ((float)(*walker).quantity_bought * (*walker).price);
walker = (*walker).next;
}
printf("Total Profit is: $%.2f\n", total);
}
int main()
{
head = NULL;
char *temp_type;
char *temp_description;
int temp_number, temp_quantity_bought, temp_quantity_sold;
float temp_price, temp_retail_price;
while(!feof(stdin))
{
scanf( "%s %ld %s %f %d %f %d\n", &temp_type, &temp_number, &temp_description, &temp_price, &temp_quantity_bought, &temp_retail_price, &temp_quantity_sold);
struct product_node *new_node;
new_node = malloc(sizeof(struct product_node));
(*new_node).next = head;
head = new_node;
(*head).supply_type = temp_type;
(*head).number = temp_number;
(*head).description = temp_description;
(*head).price = temp_price;
(*head).quantity_bought = temp_quantity_bought;
(*head).retail_price = temp_retail_price;
(*head).quantity_sold = temp_quantity_sold;
}
freopen("/dev/tty", "rw", stdin);
int done=0;
int selection=0;
while (!done)
{
printf("\nMENU OPTIONS:\n");
printf("1. Add a product number\n");//Okay
printf("2. Remove a product number\n");
printf("3. List the products for a supplier\n");
printf("4. List all unique supplier types\n");
printf("5. Show profit margin for a specific supplier type\n");
printf("6. Show total profit\n");//Okay
printf("7. Quit\n");//Okay
printf("Enter a selection (1-7): ");
scanf("%d", &selection);
char garbage = 'a';
scanf("%c", &garbage);
switch(selection){
case 1:
addProduct();
break;
case 2:
removeProduct();
break;
case 3:
listProduct();
break;
case 4:
listSupplierTypes();
break;
case 5:
supplierTypeProfit();
break;
case 6:
totalProfit();
break;
case 7:
done = 1;
break;
default:
printf("Invalid selection.\n");
break;
}
}
}
remove is the name of a standard function, declared in <stdio.h>. Defining your own object or other entity with the same name has undefined behavior. The call may be trying to store an int value at the address of the remove() function.
Try picking a different name.
UPDATE: I think I was mistaken. Function names defined in standard headers are reserved for use as identifiers with external linkage; they're also reserved for use as a macro name and as an identifier with file scope if the relevant header is #included. Neither should apply in your case. It's still a good idea to avoid defining such identifiers yourself, though.
Also, this probably isn't related to the symptom you're seeing, but
scanf("%d", &obj);
has undefined behavior if the input is a syntactically valid integer whose value is outside the range of int.
Execution does reach your "Does not get here" line. You're not seeing it because the buffered output isn't printed before the program dies. Change this:
printf("Does not get here");
to this:
printf("Does not get here\n");
fflush(stdout);
When I run your program under gdb, I see the seg fault at:
if ((*walker).number == remove)
I also get several warnings during compilation:
c.c: In function ‘addProduct’:
c.c:32:5: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char **’ [-Wformat]
c.c:38:5: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char **’ [-Wformat]
c.c: In function ‘main’:
c.c:134:9: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char **’ [-Wformat]
c.c:134:9: warning: format ‘%ld’ expects argument of type ‘long int *’, but argument 3 has type ‘int *’ [-Wformat]
c.c:134:9: warning: format ‘%s’ expects argument of type ‘char *’, but argument 4 has type ‘char **’ [-Wformat]
which could easily cause memory corruption. Fix those and see what happens.
UPDATE 2:
I don't know what other programs your code may still have, but this:
while (!(walker = NULL))
{
if ((*walker).number == remove)
{
(*prev).next = (*walker).next;
}
}
is almost certainly wrong. You're using an assignment = operator where you probably want an equality comparison ==. And after fixing that, the code would be clearer as follows:
while (walker != NULL)
{
if (walker->number == remove)
{
prev->next = walker->next;
}
}
That's just what jumped out at me when I took a very quick look after gdb told me the segfault was on the line if ((*walker).number == remove).
Try using a debugger yourself, fix one problem at a time, and pay attention to any compiler warnings.
Your printf does not appear because it didn't flush from the buffer, just use a "\n" at the end of the string and you will see it:
printf("Does not get here\n");
And so, the error, is not at scanf, but at this line:
walker = (*head).next;
As I could see, the program may reach there while head is not allocated, so you can check it at the beginning of the function:
void removeProduct(){
int remove = 0;
char kill_char = 'a';
if (head == NULL) {
printf("No product to remove!\n");
return;
}
I'm not sure if there is any other errors, but this is the one I noticed.
BTW, you can avoid using kill_char by inserting a space at the beginning and end of format string on scanf:
scanf(" %d ", &remove);
It will skip all white characters (as tabs, spaces and line breakers). And, if you really just want to skip one, and only one, character, you can use * to ignore the match:
scanf("%d%*c", &remove);

stack with finding character inside string in C language

#include <stdio.h>
#include <string.h>
main()
{
int i;
int *b, *z;
char name[30];
char vowel[5] = {'A', 'E', 'I', 'O', 'U'};
char consonants[23] = {'B','C','D','F','G','H','J','K','L','M','N','P','Q','R','S','T','V','W','X','Y','Z'};
printf ("input the string: ");
scanf ("%s", name);
printf ("The string is %s\n", name);
for (i=0; name[i]!='\0'; i++){
if
(b=strchr(vowel, name[i]) != NULL) {
printf ("The vowels are: %s\n", b); }
else if
(z=strchr(consonants, name[i]) != NULL) {
printf ("The consonants are: %s\n", z);
}
}
}
I am trying to find how many vowels and consonants in array. That's the only algorithm that our teacher showed us, but it doesn't work. Any one can point me to my mistakes?
I just did one more try, with all your advices,
#include <stdio.h>
#include <string.h>
int main()
{
int vow, cons, i;
char *s, *s1;
char name[30];
char vowel[6] = "AEIOU";
char consonants[21] = "BCDFGHJKLMNPQRSTVWXYZ";
printf ("input the string: ");
scanf ("%s", name);
printf ("The string is %s\n", name);
for (i=0; name[i]!='\0'; i++)
s = strchr(vowel, name[i]);
printf ("The vowels are: %s\n", s);
s1 =strchr(consonants, name[i])) {
printf ("The consonants are: %s\n", s1);
}
return 0;
}
This is how I changed it, with all your advices, what is my other problems? cause still dosen't work fine.
Thanks.
And this is my another version of program
#include <stdio.h>
#include <string.h>
int main()
{
int i;
int counter=0, counter2=0;
char *s;
char name[30];
char vowel[6] = "AEIOU";
char consonants[21] = "BCDFGHJKLMNPQRSTVWXYZ";
printf ("input the string: ");
scanf ("%s", name);
printf ("The string is %s\n", name);
for (i=0; name[i]!='\0'; i++) {
if (s = strchr(vowel, name[i])) {
counter++;
}
else if (s =strchr(consonants, name[i])) {
counter2++;
}
printf ("First counter is %d\n", counter);
printf ("The second counter is %d\n", counter2);
return 0;
}
}
I added counters to count quantity of vowels and consonants, still doesn't work.
strchr() is for searching in strings.
char vowel[] = "AEIOU";
char consonants[] = "BCDFGHJKLMNPQRSTVWXYZ";
#include< stdio.h>
int main()
{
int vowel=0,consonant=0;
printf ("input the string: ");
scanf ("%s", name);
printf ("The string is %s\n", name);
for(int i=0;name[i] !='\0';i++)
{
if( name[i] == 'A' || name[i] == 'E' || name[i] == 'I' || name[i] == 'O' || name[i] == 'U' )
{
vowel++;
}
else
consanant++;
}
printf("%d %d",vowel,consonant);
return 0;
}
When I compile this, I get the following messages:
$ gcc -Wall vc.c
vc.c:4:1: warning: return type defaults to ‘int’ [-Wreturn-type]
vc.c: In function ‘main’:
vc.c:17:8: warning: assignment makes pointer from integer without a cast [enabled by default]
vc.c:17:3: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
vc.c:18:4: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int *’ [-Wformat]
vc.c:20:13: warning: assignment makes pointer from integer without a cast [enabled by default]
vc.c:20:3: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
vc.c:21:4: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int *’ [-Wformat]
vc.c:24:1: warning: control reaches end of non-void function [-Wreturn-type]
So, start by making sure that your return type for main is 'int'
int main(){
and adding a return at the bottom of the function
return 0;
Thereafter, set b and z to be char *s, so that they match the return type of strchr
char *b, *z;
This will get rid of all the warnings.
$ gcc -Wall vc.c
$
Excellent. Now, when we run your program:
$ ./a.out
input the string: aaa
The string is aaa
Segmentation fault
"Segmentation fault" means you're running off the end of an array and reading memory you don't own. Now implement Ignacio Vazquez-Abrams' solution
char vowel[] = "AEIOU";
char consonants[] = "BCDFGHJKLMNPQRSTVWXYZ";
Now your program will run to completion.
$ ./a.out
input the string: AAA
The string is AAA
The vowels are: AEIOU
The vowels are: AEIOU
The vowels are: AEIOU
But it doesn't do much, does it?
So, if you're just trying to count how many vowels and consonants there are, you can just add an integer for each that increments every time the correct type is found and output them at the end:
printf("Vowels:\t%d\nConsonants:\t%d", vowelsFound, consonantsFound);
However, if you're trying to output them as lists, you're going to have much more data manipulation to do. Some links to check out:
Linux Man Page for printf
Linux Man Page for String functions
You have placed the return statement inside the for loop which is preventing it from scanning the entire name array.
When using strchr, you'll also need to convert the current loop character to uppercase for it to match properly since you have defined vowels in uppercase. To use toupper() you need to include ctype.h.
You also don't need to define consonants. What is not a vowel is a consonant.
Here's the code. I've tested it and it works:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main()
{
int i;
int counter=0, counter2=0;
char *s;
char name[30];
char vowel[6] = "AEIOU";
printf ("input the string: ");
scanf ("%s", name);
printf ("The string is %s\n", name);
for (i=0; name[i]!='\0'; i++) {
if (strchr(vowel, toupper(name[i])) != NULL) {
counter++;
}
else {
counter2++;
}
}
printf ("First counter is %d\n", counter);
printf ("The second counter is %d\n", counter2);
return 0;
}
Alternatively.
#include <stdio.h>
#include <string.h>
int main() {
int t [256];
int i,c;
int cntw = 0;
int cntc = 0;
const char * vowel="AEIOUaeiou";
const char * consonants="BCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz";
memset(t,0,256);
while (*vowel) { t[*vowel] = 1; ++vowel;}
while (*consonants) { t[*consonants] = 2; ++consonants;}
printf ("Input the text: CTRL-D to end\n");
c = getchar();
while(c >=0) {
switch(t[c]) {
case 1: ++cntw; break;
case 2: ++cntc; break;
}
c=getchar();
}
printf ("Text has %d vowel%s and %d consonant%s\n",
cntw,(cntw>1)?"s":"",
cntc,(cntc>1)?"s":"");
return 0;
}

C Program terminates after if/else or repeats if I use fputs/fgets

I am very new to C and have dabbled in Objective-C, AppleScript, and HTML/CSS. I'm sure that my problem is very easy to solve. I am trying to write something that will allow me to input source data and have it ordered in a certain way as output (in this case, citations). Basically, I want to save name, title, publisher, etc. as variables and print them in a certain order.
Here's the issue: The code here terminates too early and when I use fputs and fgets with stdout and stdin it gets stuck and asks the same question forever. What am I missing?
int source_type;
int NumberofAuthors;
char AuthorName1[20];
char AuthorName2[20];
char AuthorName3[20];
char title[20];
char url[100];
char publishingCity[20];
char publisher[20];
char yearPublished[20];
char pageNumbers[20];
int valid;
printf("Welcome to Jackson's Chicago Manual of Style Auto-Footnoter.\n");
fputs("Choose source type:\n a.Book\n b.Journal\n c.Article\n d.Website\n ", stdout);
source_type = getchar();
if (source_type == 'a') {
valid = 1;
} else {
printf("Invalid source selection");
}
while ( valid == 1 && source_type == 'a' )
{
printf("Number of authors [1 or 2]: ");
scanf( "%d", &NumberofAuthors);
if ( NumberofAuthors > 0 && NumberofAuthors < 3 ) {
valid = 1;
printf("Got it, %d author(s).\n", NumberofAuthors);
}
else {
printf( "That's not enough people to write a book.\n" );
}
if ( NumberofAuthors == 1 ) {
printf( "Author's name: " );
scanf("%c", &AuthorName1);
}
if (NumberofAuthors == 2) {
printf("First author's name: " );
scanf("%c", &AuthorName2);
printf("Second author's name: " );
scanf("%c", &AuthorName3);
}
else {
valid = 0;
}
printf("Book title: " );
fgets(title, sizeof(title), stdin);
printf("Publication city: " );
fgets(publishingCity, sizeof(publishingCity), stdin);
}
return 0;
On the beggining of the program:
if (source_type == 'a') {
valid = 1;
} else {
printf("Invalid source selection");
}
In case source_type is invalid, valid still contains garbage value, and using an uninitialized variable is undefined behaviour. Moving on.
while ( valid == 1 && source_type == 'a' )
{
printf("Number of authors [1 or 2]: ");
scanf( "%d", &NumberofAuthors);
if ( NumberofAuthors > 0 && NumberofAuthors < 3 ) {
valid = 1;
printf("Got it, %d author(s).\n", NumberofAuthors);
}
//...
You never reset valid to 0. You should consider using a switch() for that part of the while loop. It makes it more easy to read.
Also
if ( NumberofAuthors == 1 ) {
printf( "Author's name: " );
scanf("%c", &AuthorName1);
}
if (NumberofAuthors == 2) {
printf("First author's name: " );
scanf("%c", &AuthorName2);
printf("Second author's name: " );
scanf("%c", &AuthorName3);
}
else {
valid = 0;
}
I hope you realize that incase NumberofAuthors == 1 the else part is going to executed and set valid = 0. That is because the else sticks on just the closest if, and only that.
I guess you use fgets etc to avoid overflows. Good. See that trick on the scanfs. Read more here : http://www.cplusplus.com/reference/clibrary/cstdio/scanf/
Try that:
int main(int argc, char* argv[])
{
char source_type;
int NumberofAuthors;
char AuthorName1[20];
char AuthorName2[20];
char AuthorName3[20];
char title[20];
char url[100];
char publishingCity[20];
char publisher[20];
char yearPublished[20];
char pageNumbers[20];
int valid;
printf("Welcome to Jackson's Chicago Manual of Style Auto-Footnoter.\n");
printf("Choose source type:\n a.Book");
scanf("%c" , &source_type);
if (source_type == 'a') {
valid = 1;
} else {
printf("Invalid source selection");
valid = 0;
}
while ( valid == 1 && source_type == 'a' )
{
//Reset
valid = 0;
printf("Number of authors [1 or 2]: ");
scanf( "%d", &NumberofAuthors);
if ( NumberofAuthors > 0 && NumberofAuthors < 3 ) {
valid = 1;
printf("Got it, %d author(s).\n", NumberofAuthors);
}
else {
printf( "That's not enough people to write a book.\n" );
continue;
}
switch( NumberofAuthors )
{
case 1:
printf( "Author's name: " );
scanf("%19s", AuthorName1);
break;
case 2:
printf("First author's name: " );
scanf("%19s", AuthorName2);
printf("Second author's name: " );
scanf("%19s", AuthorName3);
break;
default:
valid = 0;
break;
}
if(valid)
{
printf("Book title: " );
scanf("%19s" , title);
printf("Publication city: " );
scanf("%19s" , publishingCity );
}
}
return 0;
}
You only change source_type outside of the while loop, so once entered the loop the only way to get out is by assigning 0 to valid. This is done every time NumberofAuthors != 2, since the first if is not within the if-else chain. Perhaps you want this instead:
if ( NumberofAuthors == 1 ) {
printf( "Author's name: " );
scanf("%c", &AuthorName1);
} else if (NumberofAuthors == 2) {
printf("First author's name: " );
scanf("%c", &AuthorName2);
printf("Second author's name: " );
scanf("%c", &AuthorName3);
} else {
valid = 0;
}
You are using %c to read names; this is not good. You're passing the address of an array, rather than the pointer to the first element of the array; this is also not good. You are trampling all over the place, and leaving yourself with undefined behaviour problems.
The 'obvious' fix is to use %s and forego the & in front of the array names, but you must not succumb to the obvious as it is wrong. Most authors have a space between the first and last name (or initials and surname), and %s stops at the first space. You need to use fgets() to read the names, but remember to remove the trailing newline.
It is not quite clear to me why you have a single author's name in 'AuthorName1' but double authors go in 'AuthorName2' and 'AuthorName3'; I'd expect to use 'name 1' for the first author regardless. Indeed, it might be better to have an array of author names - that generalizes more readily.
When I compile your code (wrapping it in int main(void) { and } and including <stdio.h>, I get compilation warnings:
xx.c: In function ‘main’:
xx.c:43: warning: format ‘%c’ expects type ‘char *’, but argument 2 has type ‘char (*)[20]’
xx.c:43: warning: format ‘%c’ expects type ‘char *’, but argument 2 has type ‘char (*)[20]’
xx.c:48: warning: format ‘%c’ expects type ‘char *’, but argument 2 has type ‘char (*)[20]’
xx.c:48: warning: format ‘%c’ expects type ‘char *’, but argument 2 has type ‘char (*)[20]’
xx.c:50: warning: format ‘%c’ expects type ‘char *’, but argument 2 has type ‘char (*)[20]’
xx.c:50: warning: format ‘%c’ expects type ‘char *’, but argument 2 has type ‘char (*)[20]’
I rewrote the code to use a function to handle the prompting for and reading of strings, thus:
#include <assert.h>
#include <stdio.h>
#include <string.h>
static int get_string(const char *prompt, char *buffer, size_t bufsiz)
{
char *nl;
printf("%s: ", prompt);
fflush(0);
if (fgets(buffer, bufsiz, stdin) == 0)
return EOF; /* Read error - EOF */
if ((nl = strchr(buffer, '\n')) == 0)
{
fprintf(stderr, "Overlong string entered!\n");
return EOF;
}
*nl = '\0';
return 0;
}
int main(void)
{
int source_type;
int NumberofAuthors;
char AuthorName1[20];
char AuthorName2[20];
char title[20];
char publishingCity[20];
int valid = 0;
int c;
printf("Welcome to Jackson's Chicago Manual of Style Auto-Footnoter.\n");
fputs("Choose source type:\n a.Book\n b.Journal\n c.Article\n d.Website\n ", stdout);
source_type = getchar();
if (source_type == 'a')
valid = 1;
else
{
printf("Invalid source selection");
return(1);
}
/* Lucky that scanf() skips over the newline in search of digits! */
while (valid == 1 && source_type == 'a')
{
printf("Number of authors [1 or 2]");
scanf("%d", &NumberofAuthors);
if (NumberofAuthors > 0 && NumberofAuthors < 3)
{
valid = 1;
printf("Got it, %d author(s).\n", NumberofAuthors);
}
else
{
printf("That's not enough (or too many) people to write a book.\n");
break;
}
/* Gobble to newline */
while ((c = getchar()) != EOF && c != '\n')
;
if (NumberofAuthors == 1)
{
if (get_string("Author's name", AuthorName1, sizeof(AuthorName1)) == EOF)
{
valid = 0;
break;
}
}
else
{
assert(NumberofAuthors == 2);
if (get_string("First author's name", AuthorName1, sizeof(AuthorName1)) == EOF ||
get_string("Second author's name", AuthorName2, sizeof(AuthorName2)) == EOF)
{
valid = 0;
break;
}
}
if (get_string("Book title", title, sizeof(title)) == EOF ||
get_string("Publication city", publishingCity, sizeof(publishingCity)) == EOF)
{
valid = 0;
break;
}
printf("Author 1: %s\n", AuthorName1);
if (NumberofAuthors == 2)
printf("Author 2: %s\n", AuthorName2);
printf("Book title: %s\n", title);
printf("Publication city: %s\n", publishingCity);
}
return 0;
}
I kept the 'valid' flag, but it really doesn't pay for itself. The code is simpler and shorter without it.

Resources