Error in strcmp() when I use a structure as a parameter
Asked Answered
B

6

5

My program needs these functionalities:

NOTE: I did not include the codes for the numbers 1,2 & 4 since I already finished them. The 3rd one is my problem.

  1. The program should continuously allow input from the user as long the user still wants to. (Dynamically)
  2. Get the final grade of a student (average of frst_grade, scnd_grade, fnl_grade)
  3. Get the number of students per college.
  4. Get student name by inputting s_id.

My problem is how to compare the search input to the user input in s_college to get the number of students. The only way I know is by using strcmp() but it gives me this error: invalid conversion from 'char' to 'const char*' [-fpermissive]

So how do I compare these two to get the number of students per college?

#include<stdio.h>    
#include<string.h>    
#include<conio.h>    

int i,n,sum,search,num=0,ctr=0;

char answer,choice,choice2,search2;

struct record{

int s_id;
char s_name[100];
char s_course;
char s_college[5];
int s_scoress;
}id[100],name[100],course,college[100],scores;

struct s_scores{
int frst_grade;
int scnd_grade;
int fnl_grade;
}first,second,final;



void ADD();
void COLLEGE();
void ID();


void COLLEGE(){
printf("Enter college (abbreviation only)");
scanf("%s",&search2);
for(i=0;i<num;i++){
if(strcmp(college[i].s_college,search2)==0);
ctr++;    
}  
printf("The number of students in %s is %d",search2,ctr);
Beaufert answered 15/5, 2016 at 9:6 Comment(13)
Your search2 is a char not a string. Correct it.Hollington
Push up your compiler's warning level to the maximum, then fix the code until no more warnings are issued. This "char search2; ... strcmp(...,search2)" is expected to make the compiler yell out a warning at you. Take warnings serious.Baumgardner
Do by chance you have a data file you are supposed to read values from? If so, that would also be needed here to support valid testing.Kroeger
@idmean, strongly suggest correcting your edits as the code does not compile, nor do anything useful.Notepaper
Common usage is for ALL CAPS to be used for #define and similar statements. Common usage is for function names to be either: 1) all lower case or 2) lower-camel case.Notepaper
when calling scanf() 1) always check the returned value (not the parameter value) to assure the operation was successful. 2) when using the '%s' input conversion specifier, always include a 'max length' modifier (that is one less than the length of the input buffer) so the user cannot overrun the buffer, Overrunning the buffer results in undefined behaviour and can lead to a seg fault event.Notepaper
this code: struct record{ int s_id; char s_name[100]; char s_course; char s_college[5]; int s_scoress; }id[100],name[100],course,college[100],scores; is saying there are 100 instances of the struct record in an array named id and 100 instances of the struct record in an array named name and one instance of the struct record named course and 100 instances of the struct record in an array named college and one instance of the struct record named scores. This is (most likely) not what you want.Notepaper
the code: struct s_scores{ int frst_grade; int scnd_grade; int fnl_grade; }first,second,final; is saying there are three instances of the struct scores with the names: frst_grade scnd_grade and fnl_grade. This is (most likely) not what you want.Notepaper
for ease of readability and understanding by us humans: 1) follow the axiom: only one statement per line and (at most) one variable declaration per statement. 2) separate the definition of a struct from the declarations/instances of the struct. 3) separate code blocks (for, if, else, while, do...while, switch, case, default) via a blank line.Notepaper
regarding this line: scanf("%s",&search2); the variable search2 is declared as a single char!!! Given the rest of the code snippet, the variable search2 needs to be declared as: char search[5]; The rest of the code is not posted, but I suspect this kind of error can be found else where in the code. Then when search2 is properly declared, the call to scanf() should be: if (1 != scanf( "%4s", search2 ) ) { // handle error }.Notepaper
the posted code contains several 'magic' numbers. (numbers with no basis: like 5, 100) 'magic' numbers make the code much more difficult to understand, debug, maintain. Strongly suggest using a enum statement or #define statements to give those magic numbers meaningful names, then use those meaningful names throughout the code.Notepaper
@Notepaper I just formatted the code block properly. Please learn to read edit diffs and don't abuse comments.Feuilleton
I just took another look at the posted code. There is NO indentation being used. So it is NOT formatted for readability. BTW: the 'if' code block has a body of ;, so it does nothing. If the code were properly indented (including any optional braces) then the problem of 'no body' in the 'if' code block would have been obvious.Notepaper
F
7

Lets take a look at these (partial) lines:

char ..., search2;
...
scanf("%s",&search2);
...
...strcmp(college[i].s_college,search2)...

The variable search2 is a single character. Trying to put a string into it will write at least two character: The string you read plus the string terminator. That means you will write out of bounds.

You then use the character variable as an argument to strcmp which converts the contents of search2 into a pointer and uses that pointer as a pointer to a string.

Both of these problems will lead to undefined behavior.

Is search2 supposed to be a string? Then declare it as an array, like

char ..., search2[100];

If search2 is supposed to be a single character then first you need to read a single character

scanf("%c", &search2);  // Note the changed format to read a single character

And then you need to change your comparison to not use strcmp.

Fairway answered 15/5, 2016 at 9:11 Comment(2)
I did not actually noticed that my search2 is not declared as an array. Now my whole program is working. Thank you very much!Beaufert
@JoseG.: "did not actually noticed" That's why you should take your compiler's warnings so serious! They are debugging for free! :-)Baumgardner
P
6

You cannot use strcmp with what is not a null-terminated string. You can write

if(college[i].s_college[0] == search2 && college[i].s_college[1] == '\0')

Don't forget to remove the junk semicolon to have the if statement work.

Presentiment answered 15/5, 2016 at 9:9 Comment(1)
Good solution. It however does not mention to change scanf("%s",&search2); to become scanf("%c",&search2); for the code to work.Baumgardner
R
5

Your search2 is just a character. You need a string

Perhaps declare search2 as follows:

char search2[50];

Also read up about scanf to prevent buffer overruns:

scanf("%49s", search2); // Do not go past the end of search2[50]
Riedel answered 15/5, 2016 at 9:10 Comment(0)
P
1

Well compiler tells you error: Variable search2 is char while s_college[5]; is array of chars. Function strcmp requires two arrays/pointers in order to work.

If search2 is only one byte then you can create: char Search2[2]; that would hold that one char and terminal null. But this would work only if search2 is one byte. If you however have to compare two array of chars where search2 is more then one byte, then you should probably think about dynamic allocation or create a static array char search2[some_length];.

Polybasite answered 15/5, 2016 at 9:14 Comment(1)
"But this would work only if search2 is one byte." still not even that. C-"string"s are 0-terminated. So char s[1]; would just be able to hold the empty string "".Baumgardner
N
1

this is not a complete 'answer', however, it does fix some of the major problems in the code:

Define your struct's like this;

struct s_scores
{
    int frst_grade;
    int scnd_grade;
    int fnl_grade;
};


struct record
{
    int  s_id;
    char s_name[100];
    char s_course;
    char s_college[5];
    struct s_scores  s_scoress;
};

struct record records[100];

Then access the individual fields similar to:

if( 1 != scanf( "%4s", records[i].s_college ) )
{
    perror( "scanf for college abbreviation failed" );
    exit( EXIT_FAILURE )
}

// implied else, scanf successful

// validate the college abbreviation

for( size_t j=0; j< (sizeof(collegesAbbrevationsTable)/(sizeof( *collegeAbbreviationsTable ); i++ )
{
    if( strncmp( collegeAbbreviationsTable[j], records[i].s_college, 4)
    { // then found matching abbreviation
        break; // exit 'validation' loop
    }
}

Note: perror() found in stdio.h. exit() and EXIT_FAILURE found in stdlib.h.

Note: In C, when referencing an array, the result is a pointer to the first byte of that array, so in the call to scanf() must not use & when referencing the array s_college[].

`

Notepaper answered 15/5, 2016 at 18:26 Comment(0)
M
-2

declae search2 as char search2[10]; or char * search2;

Reason : string2 is a character variable and college is a null terminating char array.

Signature of stncmp id int strcmp(const char* s1, const char*s2);

So the function to properly you need to passs char* or char array(which is again a char*).

Morphophonemics answered 15/5, 2016 at 9:15 Comment(1)
"... or char * search2;" no, don't.Baumgardner

© 2022 - 2024 — McMap. All rights reserved.