Letter guessing game in C program, confused of errors - c

I am trying to do a letter guessing game in C language by using Visual Studio 2012, but I keep getting errors and warnings and I have no clue how to fix them. The errors that I keep receiving are:
1.)Warning 1 warning C4133: 'function' : incompatible types - from 'FILE *' to 'const char *'
2.)Warning 2 warning C4047: '=' : 'FILE *' differs in levels of indirection from 'int (__cdecl *)(FILE *)'
3.)Error 3 error C2449: found '{' at file scope (missing function header?)
4.)Error 4 error C1004: unexpected end-of-file found
5.)IntelliSense: argument of type "FILE *" is incompatible with parameter
6.)IntelliSense: a value of type "int (__cdecl *)(FILE *_File)" cannot be assigned to an entity of type "FILE *"
I also see errors that say 'expected a declaration.'
Every time I try to fix things, I end up causing more issues in other areas. Could someone give me assistance with this? Thank you!
Here is my code:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#define MAXGUESSES 5
int SingleGame(char file_letter);
int main()
{
//declare additional variables
int PlayGames = 4,
i = 0;
FILE * infile;
char letter;
//display instructions
printf("Welcome to the Letter Guessing Game!\n");
printf("You will enter the number of games that you want to play, which is 1-4 games\n");
printf("You have 5 chances to guess each letter\n");
printf("Let's begin!\n");
//open file
infile = fopen("lettersin.txt", "r");
//get number of games to play
printf("How many games would you like to play?(1-4)\n");
scanf("%d", &PlayGames);
for(i=0;i<PlayGames;i++)
{
//get a letter from file
scanf(infile, " %c", &letter);
//Play one game
printf("Let's play a game %d\n", i);
//check for win or lose
SingleGame (letter);
}
//close file
infile = fclose;
return 0;
}
int SingleGame(char file_letter);
{
//Function definitions
int numGuesses = 0;
while(numGuesses < MAXGUESSES);
char RetrieveGuess = 0;
int PlayGames = 0;
{
printf("Enter a guess\n");
scanf("%c" , &RetrieveGuess);
if(file_letter == RetrieveGuess);
{
printf("You guessed it!\n");
}
else
{
if(file_letter>RetrieveGuess)
{
printf("The letter you are trying to guess comes before:%d\n",RetrieveGuess)
}
{
else if(file_letter<RetrieveGuess)
{
printf("The letter you are trying to guess comes after:%d\n", RetrieveGuess)
}
{
numGuesses = numGuesses +1;
}

1.)Warning 1 warning C4133: 'function' : incompatible types - from 'FILE *' to 'const char *'
scanf(infile, " %c", &letter);
If you want to read from a specific FILE *, use fscanf():
fscanf(infile, " %c", &letter);
2.)Warning 2 warning C4047: '=' : 'FILE *' differs in levels of indirection from 'int (__cdecl *)(FILE *)'
infile = fclose;
You want to call fclose() and not assign it to infile (which also doesn't have a compatible type):
fclose(infile);
3.)Error 3 error C2449: found '{' at file scope (missing function header?)
int SingleGame(char file_letter);
The semicolon makes that a function declaration/protoype, but you want to define one. Delete it.
The semicolon here is a so-called null statement). This means if both variables are equal, then nothing will be done.
if(file_letter == RetrieveGuess);

You have a number of issues with your code here. It is always difficult to work on more than one problem at a time. My advice is that you copy all this code into a different file, and rebuild this file one line at a time and only add another line after you compile the current file error and warning free.

Lots of syntax errors were in code. I've corrected them for you. Although not sure logically the code is correct or not. You got to run and see.
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#define MAXGUESSES 5
void SingleGame(char file_letter);
int main()
{
//declare additional variables
int PlayGames = 4,
i = 0;
FILE* infile;
char letter;
//display instructions
printf("Welcome to the Letter Guessing Game!\n");
printf("You will enter the number of games that you want to play, which is 1-4 games\n");
printf("You have 5 chances to guess each letter\n");
printf("Let's begin!\n");
//open file
infile = fopen("lettersin.txt", "r");
//get number of games to play
printf("How many games would you like to play?(1-4)\n");
scanf("%d", &PlayGames);
for(i=0;i<PlayGames;i++)
{
//get a letter from file
fscanf(infile, " %c", &letter);
//Play one game
printf("Let's play a game %d\n", i);
//check for win or lose
SingleGame (letter);
}
//close file
fclose(infile);
return 0;
}
void SingleGame(char file_letter)
{
//Function definitions
int numGuesses = 0;
while(numGuesses < MAXGUESSES)
{
char RetrieveGuess = 0;
int PlayGames = 0;
printf("Enter a guess\n");
scanf("%c" , &RetrieveGuess);
if(file_letter == RetrieveGuess)
{
printf("You guessed it!\n");
}
else
{
if(file_letter>RetrieveGuess)
{
printf("The letter you are trying to guess comes before:%d\n",RetrieveGuess);
}
else if(file_letter<RetrieveGuess)
{
printf("The letter you are trying to guess comes after:%d\n", RetrieveGuess);
}
numGuesses = numGuesses +1;
}
}
}

Related

format specifies type 'int *' but the argument has type 'int' [-Wformat] in C language when typing scanf("%d", (*(pArr[i])).age);

I have a program where I have to add a name, age and 2 courses for a student in a database using pointer structures and pointer arrays in C. I am able to store the name entered by the user into the database but not the age. When I enter age, this error shows up "format specifies type 'int ' but the argument has type 'int' [-Wformat]
scanf("%d", ((pArr[i])).age);"
I know that this could be a common error but I am a bit new to C. Any help would be appreciated.
My function for entering new values looks like:-
Also, this code is still in development, so please point me out any extra errors if there are :)
//global
#define SIZE 30
#define fieldLength 200
struct db_type
{
char name[fieldLength];
int age;
char course1[fieldLength];
char course2[fieldLength];
char status[fieldLength];
};
struct courseInfo
{
char code [20]; // e.g., EECS2030
char title [fieldLength];
char date [20];
char time_start [20];
char time_end [20];
char location [20];
};
struct courseInfo courseArr[SIZE];
int main(int argc, char *argv[])
{
struct db_type * db_pArr[SIZE]; // main db storage
init_list(db_pArr); // set to NULL
init_courseArr(); // load course from diskfile
char choice;
for(; ;){
choice = prompt_menu();
switch (choice)
{
case 'n': enterNew(db_pArr); break;
case 'q': exit(1); // terminate the whole program
}
}
return 0;
}
void enterNew(struct db_type * pArr[SIZE]){
static int i=0;
static int j=0;
int flag = 0;
pArr[i] = malloc(sizeof(struct db_type));
printf("name: ");
scanf("%s", (*pArr[i]).name);
printf("age: ");
scanf("%d", (*(pArr[i])).age); //error here
printf("course-1: ");
scanf("%s", (*pArr[i]).course1);
while(flag == 0)
for(int j=0; j<SIZE; j++){
if(strcmp((*pArr[i]).course1, courseArr[j].code) == 1 && flag == 0){
printf("course does not exist, enter again: \n");
printf("course-1: ");
scanf("%s", (*pArr[i]).course1);
}
else
flag = 1;
}
if(flag == 1)
++i;
// further code in development
// printf("course-2: ");
// scanf("%s", pArr[i].course2);
}
Further extra information about what program does
-> This program basically is a part of a student database management system. When user enters 'n' or 'N', this function is invoked. User has the option to enter student name, age, student's course-1 and course-2. It also has to check whether course-1 and course-2's start time and end time clash or not and store it in a variable called char status[] of structure db_type.
Change
scanf("%d", (*(pArr[i])).age);
to
scanf("%d", &(*(pArr[i])).age);
scanf() requires a pointer to the variable and adding & in front of it returns the pointer of the variable.

Calculating Average from array and seperate structure

Trying to make a program that prints data entered into a file.
Everything is working all and good apart from the Calculating Average for marks entered.
I can't seem to figure out how to do it, even though it should be simple I just cant get my head around it.
The error I am currently getting is:
"temp->mark = temp->mark + studentArray[j];" (Invlalid operands to
binary + (have 'float' and 'char *').
Much appreciated if someone could help me. I have tried the following
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
struct student{
char name[30];
int id;
float mark;
};
int count = 0;
void student_update(char *stuadd);
void display(char *stuadd);
void main(int argc, char *studentArray[100])
{
int choice;
while(1)
{
printf("Welcome to Student Archives\n\n");
printf("1. Display Students' Details\n");
printf("2. Calculate average of all students’ marks \n");
printf("3. Add new student to the record \n");
printf("4. Quit Program\n");
scanf("%d",&choice);
switch(choice)
{
case 1:display(studentArray[100]);
break;
case 2:
break;
case 3:
student_update(studentArray[100]);
break;
case 4: printf("Program Terminated.\n");
exit(0);
default: printf("Wrong Choice. Enter again\n");
break;
}
}
}
void display(char *stuadd)
{
FILE *fptr;
char ch;
int rec = count;
fptr = fopen("stuadd.txt", "r");
struct student *temp = (struct student *)malloc(sizeof(struct student));
if (fptr == NULL)
printf("File does not exist.");
else
{
while (rec)
{
fread(temp->name, 50, 1, fptr);
printf(" %s\n", temp->name);
fread(&temp->id, sizeof(int), 1, fptr);
printf("%d", temp->id);
fread(&temp->mark, sizeof(int), 1, fptr);
printf("%.2f", temp->mark);
rec--;
}
}
fclose(fptr);
free(temp);
free(temp->name);
}
void calculateAverage(char *studentArray[100])
{
struct student *temp = (struct student *)malloc(sizeof(struct student));
int j;
float avg;
temp->mark = avg = 0;
for(j = 0; j < 100; j++)
{
temp->mark = temp->mark + studentArray[j];
}
avg = (float)temp->mark / j;
printf("Average of students' total marks are: %.2f",avg);
}
void student_update(char *stuadd)
{
FILE *fptr;
fptr = fopen("stuadd.txt", "a+");
struct student *temp = (struct student *)malloc(sizeof(struct student));
if (fptr == NULL)
printf("\nError.");
else
{
printf("\nEnter the students' name\n");
scanf(" %[^\n]s", temp->name);
printf("Enter the students' ID\n");
scanf("%d", &temp->id);
printf("Enter the students' mark\n");
scanf("%f", &temp->mark);
fprintf(fptr, "%s %d %.2f", temp->name, temp->id, temp->mark);
count++;
}
fclose(fptr);
free(temp);
free(temp->name);
}
The posted code does not compile!
under ubuntu linux, using:
gcc -ggdb -Wall -Wextra -Wconversion -pedantic -std=gnu11 -c "untitled.c" (in directory: /home/richard/Documents/forum)
the compiler outputs the following:
untitled.c:16:6: warning: return type of ‘main’ is not ‘int’ [-Wmain]
void main(int argc, char *studentArray[100])
^~~~
untitled.c: In function ‘main’:
untitled.c:16:15: warning: unused parameter ‘argc’ [-Wunused-parameter]
void main(int argc, char *studentArray[100])
^~~~
untitled.c: In function ‘display’:
untitled.c:48:10: warning: unused variable ‘ch’ [-Wunused-variable]
char ch;
^~
untitled.c:45:20: warning: unused parameter ‘stuadd’ [-Wunused-parameter]
void display(char *stuadd)
^~~~~~
untitled.c: In function ‘calculateAverage’:
untitled.c:83:33: error: invalid operands to binary + (have ‘float’ and ‘char *’)
temp->mark = temp->mark + studentArray[j];
~~~~~~~~~~ ^ ~~~~~~~~~~~~~~~
untitled.c:86:29: warning: conversion to ‘float’ from ‘int’ may alter its value [-Wconversion]
avg = (float)temp->mark / j;
^
untitled.c: In function ‘student_update’:
untitled.c:91:27: warning: unused parameter ‘stuadd’ [-Wunused-parameter]
void student_update(char *stuadd)
^~~~~~
Compilation failed.
There are some other problems, like:
free(temp);
free(temp->name);
That is accessing a pointer into allocated memory after the allocated memory has been passed to free() The result is indefined behavior. Suggest:
free(temp->name);
free(temp);
Regarding the following statements
FILE *fptr;
fptr = fopen("stuadd.txt", "a+");
struct student *temp = (struct student *)malloc(sizeof(struct student));
if (fptr == NULL)
printf("\nError.");
Always check for an error indication immediately after the call to the C library function.
output error messages to stderr, not stdout
When the error indication is from a C library function, then immediately call perror(); to output both your error message AND the text reason the system thinks the error occurred, all to stderr
when calling any of the heap allocation functions: malloc calloc realloc, 1) the returned type is void* which can be assigned to any pointer. Casting just clutters the code, making it more difficult to understand, debug, etc. 2) always check (!=NULL) the returned value to assure the operation was successful. Suggest:
FILE *fptr;
fptr = fopen("stuadd.txt", "a+");
if ( !fptr )
{
perror("fopen failed");
exit( EXIT_FAILURE );
}
// implied else, fopen successful
struct student *temp = malloc(sizeof(struct student));
if( !temp )
{
perror( "malloc failed" );
exit( EXIT_FAILURE );
}
// implied else, malloc successful
regarding:
scanf(" %[^\n]s", temp->name);
That call to scanf() is nonsense. Since the input format specifier %[^\n] will stop input from stdin when it encounters a newline sequence, there is no possible way for the next char in stdin to be a s When calling any of the scanf() family of functions, always check the returned value to assure the operation was successful. when using the input format specifiers %s and/or %[...] always include a MAX CHARACTERS modifier that is one less than the length of the input buffer to avoid any possibility of buffer overflow (and the resulting undefined behavior). Suggest removing the trailing s in the format string and check the return value and limiting the total number of characters that can be input, as in:
if( scanf(" %29[^\n]", temp->name) != 1 )
{
fprintf( stderr, "scanf failed to input the student name\n" );
exit( EXIT_FAILURE );
}
regarding:
for(j = 0; j < 100; j++)
{
temp->mark = temp->mark + studentArray[j];
}
there is no array studentArray[] so this will never produce the desired results.
regarding the error message:
avg = (float)temp->mark / j;
untitled.c:83:33: error: invalid operands to binary + (have ‘float’ and ‘char *’)
temp->mark = temp->mark + studentArray[j];
of course a 'float` value cannot be added to a pointer to a char array. What were you actually trying to accomplish?
All the above is just the 'tip of the iceburg' of problems in the posted code. Suggest using a debugger and stepping through your code to determine the many problems

Storing user input whilst still asking questions

Firstly, i know the source code below is long and you're not really supposed to post code like this, but i really don't understand why it's not working or how i could explain my issue without posting it like this.
Im trying to store the answer to each of the questions asked in it and display them at the end of the script. The biggest problem im having is that i get the error
"subscripted value is neither array nor pointer nor vector scanf("%s", a[i].incdest);"
The program doesn't accept a[i].incdest. it does this for all of the array values.
it is also saying that in function main variable "comp1" is undeclared.
#include<stdio.h>
#include<string.h>
int c_s(char*, char*);
typedef struct
{
char constab[30];
char vicwit[15];
char witdet[200];
char incdest[300];
char comp1[15];
char comp2[200];;
} sheetstore;
#define ARRAYLEN 2
sheetstore a[ARRAYLEN];
FILE *fp;
int main()
{
int i, a;
char wit[10] = "witness";
char yes[10] = "yes";
char comp1[10];
fp = fopen("sheetstore.dat","a+");
printf("Hate crime reporting system\n\n\n");
printf("If the crime you are reporting is an emergency,\nplease call 999, do not proceed any further with this form\n\n\n\nPlease press enter to confirm you have read the above and continue\n");
char enter = 0;
while (enter != '\r' && enter != '\n') { enter = getchar(); }
for( i=0; i<ARRAYLEN ; i++)
{
printf("Which police constabulary did the offence take place in?\n\n");
scanf("%s", a[i].constab);
printf("Are you a victim or witness of the crime?\nPlease answer victim/witness\n\n");
scanf("%s", a[i].comp1);
int res1 = (strcmp (comp1, wit));
if(res1 == 0){
printf("Please enter the details including phone number and address of any other witnesses that were present\n");
}
scanf("%s", a[i].witdet);
else{
printf("Where did the incident take place?\nIf in a house please provide the full address including postcode\n");
scanf("%s", a[i].incdest);
}
fwrite(&a[i], sizeof(a), 1, fp);
}
fclose(fp);
fopen("sheetstore.dat", "r");
for(i=0; i<ARRAYLEN; i++)
{
fread(&a[i], sizeof(a), 1, fp );
printf("Which police constabulary did the offence take place in? : %s\n", a[i].constab);
printf("Are you a victim or witness of the crime? : %s\n", a[i].comp1);
printf("Please enter the details including phone number and address of any other witnesses that were present : %s\n", a[i].witdet);
printf("Where did the incident take place? : %s\n", a[i].incdest);
}
fclose(fp);
return 0;
}
the main issue that i saw in your code, is that you shadowed the array a (sheetstore a[ARRAYLEN];) by declaring an int with the same name in your main().
you also had a scanf stament mislocated.
i fixed your code and put in a comment for every change - now, i don't persume to check the functionality of your code but at least this will compile and hopefully will give you a better understanding where you were wrong - from here it is up to you:
#include<stdio.h>
#include<string.h>
int c_s(char*, char*);
typedef struct
{
char constab[30];
char vicwit[15];
char witdet[200];
char incdest[300];
char comp1[15];
char comp2[200];;
} sheetstore;
#define ARRAYLEN 2
sheetstore sheetArr[ARRAYLEN]; //change this 'a' to avoid shadowing by the decleration on 'int a' in main
FILE *fp;
int main()
{
int i, a;
char wit[10] = "witness";
char yes[10] = "yes";
char comp1[10];
fp = fopen("sheetstore.dat","a+");
printf("Hate crime reporting system\n\n\n");
printf("If the crime you are reporting is an emergency,\nplease call 999, do not proceed any further with this form\n\n\n\nPlease press enter to confirm you have read the above and continue\n");
char enter = 0;
while (enter != '\r' && enter != '\n') { enter = getchar(); }
for( i=0; i<ARRAYLEN ; i++)
{
printf("Which police constabulary did the offence take place in?\n\n");
scanf("%s", sheetArr[i].constab);//change name from 'a'
printf("Are you a victim or witness of the crime?\nPlease answer victim/witness\n\n");
scanf("%s", sheetArr[i].comp1);//change name from 'a'
int res1 = (strcmp (sheetArr[i].comp1, wit));//compare with the value set in the struct
if(res1 == 0){
printf("Please enter the details including phone number and address of any other witnesses that were present\n");
/*this scanf should be inside the brackets of 'if(res1 == 0)' */
scanf("%s", sheetArr[i].witdet);//change name from 'a'
}
else{
printf("Where did the incident take place?\nIf in a house please provide the full address including postcode\n");
scanf("%s", sheetArr[i].incdest);//change name from 'a'
}
fwrite(&sheetArr[i], sizeof(sheetstore), 1, fp);//write a single struct
}
fclose(fp);
fopen("sheetstore.dat", "r");
for(i=0; i<ARRAYLEN; i++)
{
fread(&sheetArr[i], sizeof(sheetstore), 1, fp );//read a single struct
printf("Which police constabulary did the offence take place in? : %s\n", sheetArr[i].constab);
printf("Are you a victim or witness of the crime? : %s\n", sheetArr[i].comp1);
printf("Please enter the details including phone number and address of any other witnesses that were present : %s\n", sheetArr[i].witdet);
printf("Where did the incident take place? : %s\n", sheetArr[i].incdest);
}
fclose(fp);
return 0;
}
In addition to some useful comments posted above (meaningful variable names, line width not to be too long for readability), in general sense, your problem is due to two thing: in the body of the main function you declare an int a which is used instead of your global array a[ARRAYLEN]. Hence, you cannot refence a[i].incdet etc. Just comment or remove the int a from the main function. Secondly, your scanf("%s", a[i].witdet); should be in the body of the if statement above according to the program logic. I you do these two changes, the code will compile. However if you pass -Wall -Werror to the compiler, it will yields an error like error: unused variable ‘yes’ [-Werror=unused-variable]
char yes[10] = "yes";. Just comment this line to avoid using uncessary memory space on the stack.
The following proposed code:
corrects the first 50+ lines of your code.
Please correct your posted code so it cleanly compiles
for flexibility, separates the definition of the struct from the typedef of the struct
properly checks for error indications from system functions
honors the right margin (usually 72 or 80 characters)
replaces the CPU cycle intensive calls to printf() with calls to puts() when appropriate
This is only a guide for the first 50 lines of the OPs code. It is not a complete code replacement.
and now the proposed code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// prototypes
int c_s(char*, char*);
struct sSheet
{
char constab[30];
char vicwit[15];
char witdet[200];
char incdest[300];
char comp1[15];
char comp2[200];
};
typedef struct sSheet sheetstore;
#define ARRAYLEN 2
sheetstore a[ARRAYLEN];
FILE *fp;
int main( void )
{
int i;
char wit[10] = "witness";
//char yes[10] = "yes";
char comp1[10];
fp = fopen("sheetstore.dat","a+");
if( !fp )
{
perror( "fopen for appending to 'sheetstore.dat' failed" );
exit( EXIT_FAILURE );
}
// implied else, fopen successful
puts("Hate crime reporting system\n\n\n");
puts("If the crime you are reporting is an emergency,\n"
"please call 999, "
" do not proceed any further with this form\n\n\n\n"
"Please press enter"
" to confirm you have read the above and continue\n");
int enter = 0;
while (enter != '\r' && enter != '\n')
{
enter = getchar();
}
for( i=0; i<ARRAYLEN ; i++)
{
puts("Which police constabulary did the offence take place in?\n\n");
if( scanf("%29s", a[i].constab) != 1)
{
fprintf( stderr, "scanf for which police constabulary failed" );
fclose( fp ); // cleanup
exit( EXIT_FAILURE );
}
// implied else, scanf successful

Creating text file in C, using VC++ Express

Okay this is kind of an odd question, but I have no idea why this doesn't work...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_NAME 15
#define MAX_SUBSEC 3
#define N 128
struct student{
int term;
int id;
char lastname[MAX_NAME];
char firstname[MAX_NAME];
char subjectnam[MAX_SUBSEC];
int subject;
int catalog;
char section[MAX_SUBSEC];
}students[10];
int main(){
int i;
char poop[10];
char fname[128];
printf("Enter the name of the text file: ");
scanf("%123s",fname);
strcat(fname,".txt");
FILE *inputf;
inputf = fopen(fname,"w");
if (inputf == NULL){
printf("I couldn't open results.dat for writing.\n");
exit(0);
}
printf("Enter first name: "); scanf("%s", poop);
fprintf(inputf, "%s\n", poop);
for (i=0; i<=10; ++i)
fprintf(inputf, "%d, %d\n", i, i*i);
fclose(inputf);
return 0;
}
Now the end of this code is just me practicing creating the file and writing to it and all that good stuff. When I coded this and ran it on my Mac using NetBeans it worked fine, I'm doing this all in C by the way, NOT C++. Now I want to do it here on my desktop and Visual wont have it, doesnt do anything but open the cmd window, take in the first line where it says to enter the file name, I do and press enter and the program closes down and terminates. I have added the source file item and named it with the proper *.c extension, and I have coded *.c in this IDE before but never had to create a file til now, which I can guarantee is the issue. Anyone have any idea why this all happens?
EDIT: I've broken up some code to try and pinpoint the issues and it seems as though these lines are the cause...
FILE *inputf;
inputf = fopen(fname,"w");
When I attempt to build and run I get some typical VC error message and this in my output about these "indiscretions"
"error C2275: 'FILE' : illegal use of this type as an expression"
"error C2065: 'inputf' : undeclared identifier"
"warning C4047: '=' : 'int' differs in levels of indirection from 'FILE *'"
So why is it that these lines work totally fine on NetBeans on my Mac, but not here on Windows? Some sort of portability issue I imagine?
This is happening because CL.exe(Microsoft Compiler) does not allow declaration of variables in code. It requires you define variables at the start of a function or a block.
Sadly, even though it is C99 standard, Even CL.exe for MSVC++ 2010 does not support it!
Change your code to:
int main(){
int i;
char poop[10];
char fname[128];
FILE *inputf;
printf("Enter the name of the text file: ");
scanf("%123s",fname);
strcat(fname,".txt");
inputf = fopen(fname,"w");
if (inputf == NULL){
printf("I couldn't open results.dat for writing.\n");
exit(0);
}
printf("Enter first name: "); scanf("%s", poop);
fprintf(inputf, "%s\n", poop);
for (i=0; i<=10; ++i)
fprintf(inputf, "%d, %d\n", i, i*i);
fclose(inputf);
return 0;
}

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);

Resources