strcmp() function in C [closed] - c

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 4 years ago.
Improve this question
I'm using the strcmp() fucntions to test how it works.
Ok,there is strcmp(string1,string2) that says us is ti string1 greater or smaller than string2 .
Here is my code to test this function:
#include<stdio.h>
#include<string.h>
char string1[20];
char string2[20];
int main()
{
int test;
printf("Enter 'string1'\n");
scanf("%s",&string1);
printf("Enter 'string2'\n");
scanf("%s",&string2);
test=strcmp(string1,string2);
if(test>0)
printf("String 'string1' is greater than 'string2'\n");
else if(test<0)
printf("String 'string1' is less than 'string2'\n");
else if(test==0)
printf("\n String 'string1'is equal to 'string2'");
printf("\n The value of 'test' is :%d",test);
return 0;
}
the test variable is always 1 and 'string1' is always greater than 'string2' .
pls help

strcmp is unlikely the problem. Here are a few things you can do to troubleshoot the problem.
Make sure to prevent overflow when using scanf.
Make sure that the calls to scanf are successful.
Add a line of code to print what was read so you know the values being passed to strcmp.
You don't need to use &string1 to read a string. Use just string1. Same with string2.
printf("Enter 'string1'\n");
// Read at most 19 characters from the stream, leaving space
// for the null terminator.
if ( scanf("%19s", string1) != 1 )
{
// Problem reading into string1.
printf("Unable to read string1\n");
}
printf("Enter 'string2'\n");
if ( scanf("%19s", string2) != 1 )
{
// Problem reading into string2.
printf("Unable to read string2\n");
}
printf("Input strings...\nstring1: \"%s\", string2: \"%s\"\n", string1, string2);

You should write like this, because the problem is in the scanf:
printf("Enter 'string1'\n");
scanf("%s",string1);
printf("Enter 'string2'\n");
scanf("%s",string2);
Don't use the & when you try read a string/pointer.
E.g:
char *str;
scanf("%s", str);
You can use the fread(string1, 20, stdin) to previne the string overflow
You can try the code here

The problem in your code is that while receiving string from the user , you are storing the string using scanf("%s",&string1) , You need to understand that &string1 and string1 both gives the same address,but they both are very much different.When you increment &string1 ,it points to 80 bytes further from the base address because on incrementing a pointer it points to the same location of its type ,&string1 means base address of whole array while string1 means address of the first element,so when you increment it ,it points to 4 bytes further from the base address.So when you give an address to scanf to store a string ,be careful what type of address you are giving otherwise it may give you some undefined behaviour.In your program just in place of &string1 use string1 in scanf to receive string, the remaining program is correct.

Related

pointer and char array [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I am using gcc 4.9.2-10 deb8u1 compiler to compile
Here is my code
#include <stdio.h>
int main(){
char *s;
char sa[10] , sb[10];
scanf("%s", sa);
printf("line\n");
scanf("%s", sb);
printf("%s %s", sa, sb);
}
Above code is no any problem if char is under the space provided
However
scanf("%s", s);
printf("line\n");
scanf("%s", sa);
printf("%s %s", s, sa);
Input:
$:
Hu
Result:
line
(null) Hu
Someone could told me what happen about second code wrong .?
I cannot figure out why i cannt input second one .. Thx a lot .!
In you code
char *s;
char sa[10] , sb[10];
you can't do much with s.
scanf("%s", sa);
is ok, provided the input fits. You can jump through a few hoops, reading the inputs in chunks in a loop if it might be longer (see here)
However, in you "However" section of the question you try
scanf("%s", s);
Since s doesn't point to memory - you'd need to have allocated some - you have undefined behaviour, so anything could happen.
I cannot figure out why i cannt input second one ? because s is not initialize and not having any valid address & doing scanf() on that results in undefined behaviour.
First allocate the memory and then scan the user input.
int main() {
char *s; /* its un initialized */
s = malloc(size); /* this you need to do ? specify the size value */
fgets(s,size,stdin);/* its advisable as its not having overflow problem */
printf("%s\n",s);
/* once job is done , free it by calling free(s) */
free(s);
return 0;
}
Use fgets() instead of scanf() to scan the user input for the reason listed in comments.

C - Using fgets until newline/-1 [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
So I'm trying to make it so that you can write text into a file until you make a newline or type -1. My problem is that when you write, it just keeps going until it crashes and gives the error "Stack around the variable "inputChoice" was corrupted".
I believe the problem is that the program doesn't stop accepting stdin when you want to stop typing (-1, newline) and that causes the error. I've tried with a simple scanf and it works, but you can only write a word. No spaces and it doesn't support multiple lines either. That's why I have to use fgets
Judging from your comments, I assume that there are some basic concepts in C
that you haven't fully understood, yet.
C-Strings
A C-String is a sequence of bytes. This sequence must end with the value 0.
Every value in the sequence represents a character based on the
ASCII encoding, for example the
character 'a' is 97, 'b' is 98, etc. The character '\0' has
the value 0 and it's the character that determines the end of the string.
That's why you hear a lot that C-Strings are '\0'-terminated.
In C you use an array of chars (char string[], char string[SOME VALUE]) to
save a string. For a string of length n, you need an array of dimension n+1, because
you also need one space for the terminating '\0' character.
When dealing with strings, you always have to think about the proper type,
whether your are using an array or a pointer. A pointer
to char doesn't necessarily mean that you are dealing with a C-String!
Why am I telling you this? Because of:
char inputChoice = 0;
printf("Do you wish to save the Input? (Y/N)\n");
scanf("%s", &inputChoice);
I haven't changed much, got very demotivated after trying for a while.
I changed the %s to an %c at scanf(" %c, &inputChoice) and that
seems to have stopped the program from crashing.
which shows that haven't understood the difference between %s and %c.
The %c conversion specifier character tells scanf that it must match a single character and it expects a pointer to char.
man scanf
c
Matches a sequence of characters whose length is specified by the maximum field
width (default 1); the next pointer must be a
pointer to char, and there must be enough room for all the characters
(no terminating null byte is added). The usual skip of
leading white space is suppressed. To skip white space first, use an explicit space in the format.
Forget the bit about the length, it's not important right now.
The important part is in bold. For the format scanf("%c", the function
expects a pointer to char and its not going to write the terminating '\0'
character, it won't be a C-String. If you want to read one letter and one
letter only:
char c;
scanf("%c", &c);
// also possible, but only the first char
// will have a defined value
char c[10];
scanf("%c", c);
The first one is easy to understand. The second one is more interesting: Here
you have an array of char of dimension 10 (i.e it holds 10 chars). scanf
will match a single letter and write it on c[0]. However the result won't be
a C-String, you cannot pass it to puts nor to other functions that expect
C-Strings (like strcpy).
The %s conversion specifier character tells scanf that it must match a sequence of non-white-space characters
man scanf
s
Matches a sequence of non-white-space characters; the next pointer must be a
pointer to the initial element of a character array that is long enough to
hold the input sequence and the terminating null byte ('\0'), which is added
automatically.
Here the result will be that a C-String is saved. You also have to have enough
space to save the string:
char string[10];
scanf("%s", string);
If the strings matches 9 or less characters, everything will be fine, because
for a string of length 9 requires 10 spaces (never forget the terminating
'\0'). If the string matches more than 9 characters, you won't have enough
space in the buffer and a buffer overflow (accessing beyond the size) occurs.
This is an undefined behaviour and anything can happen: your program might
crash, your program might not crash but overwrites another variable and thus
scrwes the flow of your program, it could even kill a kitten somewhere, do
you really want to kill kittens?
So, do you see why your code is wrong?
char inputChoice = 0;
scanf("%s", &inputChoice);
inputChoice is a char variable, it can only hold 1 value.
&inputChoice gives you the address of the inputChoice variable, but the
char after that is out of bound, if you read/write it, you will have an
overflow, thus you kill a kitten. Even if you enter only 1 character, it will
write at least 2 bytes and because you it only has space for one character, a kitten will die.
So, let's talk about your code.
From the perspective of an user: Why would I want to enter lines of text, possibly a lot of lines of text
and then answer "No, I don't want to save the lines". It doesn't make sense to
me.
In my opinion you should first ask the user whether he/she wants to save the
input first, and then ask for the input. If the user doesn't want to save
anything, then there is no point in asking the user to enter anything at
all. But that's just my opinion.
If you really want to stick to your plan, then you have to save every line and
when the user ends entering data, you ask and you save the file.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFERLEN 1024
void printFile () {
int i;
char openFile[BUFFERLEN];
FILE *file;
printf("What file do you wish to write in?\n");
scanf("%s", openFile);
getchar();
file = fopen(openFile, "w");
if (file == NULL) {
printf("Could not open file.\n");
return;
}
// we save here all lines to be saved
char **lines = NULL;
int num_of_lines = 0;
char buffer[BUFFERLEN];
printf("Enter an empty line of -1 to end input\n");
// for simplicity, we assume that no line will be
// larger than BUFFERLEN - 1 chars
while(fgets(buffer, sizeof buffer, stdin))
{
// we should check if the last character is \n,
// if not, buffer was not large enough for the line
// or the stream closed. For simplicity, I will ignore
// these cases
int len = strlen(buffer);
if(buffer[len - 1] == '\n')
buffer[len - 1] = '\0';
if(strcmp(buffer, "") == 0 || strcmp(buffer, "-1") == 0)
break; // either an empty line or user entered "-1"
char *line = strdup(buffer);
if(line == NULL)
break; // if no more memory
// process all lines that already have been entered
char **tmp = realloc(lines, (num_of_lines+1) * sizeof *tmp);
if(tmp == NULL)
{
free(line);
break; // same reason as for strdup failing
}
lines = tmp;
lines[num_of_lines++] = line; // save the line and increase num_of_lines
}
char inputChoice = 0;
printf("Do you wish to save the Input? (Y/N)\n");
scanf("%c", &inputChoice);
getchar();
if (inputChoice == 'Y' || inputChoice == 'y') {
for(i = 0; i < num_of_lines; ++i)
fprintf(file, "%s\n", lines[i]); // writing every line
printf("Your file has been saved\n");
printf("Please press any key to continue");
getchar();
}
// closing FILE buffer
fclose(file);
// free memory
if(num_of_lines)
{
for(i = 0; i < num_of_lines; ++i)
free(lines[i]);
free(lines);
}
}
int main(void)
{
printFile();
return 0;
}
Remarks on the code
I used the same code as yours as the base for mine, so that you can spot the
differences much quicker.
I use the macro BUFFERLEN for declaring the length of the buffers. That's
my style.
Look at the fgets line:
fgets(buffer, sizeof buffer, stdin)
I use here sizeof buffer instead of 1024 or BUFFERLEN. Again, that's my
style, but I think doing this is better, because even if you change the size
of the buffer by changing the macro, or by using another explicit size, sizeof buffer
will always return the correct size. Be aware that this only works when
buffer is an array.
The function strdup returns a pointer a pointer to a new string that
duplicates the argument. It's used to create a new copy of a string. When
using this function, don't forget that you have to free the memory using
free(). strdup is not part of the standard library, it conforms
to SVr4, 4.3BSD, POSIX.1-2001. If you use Windows (I don't use Windows,
I'm not familiar with the Windows ecosystem), this function might not be
present. In that case you can write your own:
char *strdup(const char *s)
{
char *str = malloc(strlen(s) + 1);
if(str == NULL)
return NULL;
strcpy(str, s);
return str;
}

Consecutive scanf is adding up strings [duplicate]

This question already has answers here:
How to prevent scanf causing a buffer overflow in C?
(6 answers)
Closed 6 years ago.
I've been having a problem with a very simple program and I really don't know why. There is a struct for a person:
typedef struct {
char name[50];
char p_id[11];
char cel[11];
int by;
int id;
} Person;
Now, there is another struct which stands for the list of contacts:
typedef struct {
Person * people;
} lContacts;
I've been trying to include the person's data to it, and add that person to the contact list. The person is being added normally, so I won't post the code here, but there is something wrong happening when I read the string:
void include(lContacts * myContacts)
{
Person p;
scanf("%s", p.name);
scanf("%d", &p.by); //birth year
scanf("%s", p.p_id);
printf("TEST P_ID: %s\n\n", p.p_id);
scanf("%s", p.cel);
printf("TEST P_ID AGAIN: %s\n\n", p.p_id);
myContacts->people[index]=p; //don't worry about the index, there is a piece of code I'm omitting to make it easier to read, just assume it is right.
}
}
Notice that I have a print test there, because when I listed my contacts, the contact p_id had itself concatenated with the cel, so I printed the whole code until I found the mistake was there.
Here is a input example:
Name
1991
11111111111
<console prints| TEST P_ID: 11111111111>
22222222222
<console prints| TEST P_ID AGAIN: 1111111111122222222222>
however, if I print p.cel, it is correctly printed
<console prints 22222222222>
Any ideas? Maybe I should use '&' when scanning strings? (I read about it and the way I understood, there is no need.. is that right?)
This is actually a very minute mistake here. Basically, you are experiencing a Buffer Overflow in the string p.p_id.
When you input the value for p.p_id as 11111111111 (11 times 1), you must realise that the actual capacity for the p_id string is declared as just 11 which must include the NULL character at the end.
If you assign 11111111111 to p_id there will be no space left for the NULL character in that string and so there will NOT be any at its end.
When you input the value for next member string of the structure, the same happens there, too.
Now, when you are trying to print the value of p.p_id the value will print until a '\0' (NULL character) is found in the string. But, there is none here, so the next string will start printing! (The buffer or string p_id overflows)
This is happening due to the member alignment done in structures in C. The next string will be stored in a consecutive memory cell, so the printing will continue. (If there was a third consecutive string member, then due to the buffer overflow in the second string, it will print too!)
But, the printing stops after second string because either there is no data in the next consecutive memory cell due to certain struct alignment or there may be an actual 0 value in the next cell which is interpreted as NULL character.
To avoid, either use a larger size for the character array or use dynamically allocated strings.
As #skrtbhtngr pointed out, you have a buffer overflow. In order to prevent this in the future, you should use fgets instead of scanf on unknown string inputs. This example will exit(1) if the input is corrupted.
int getsafestring(char* s, int maxlen)
{
if(fgets(s,maxlen,stdin) == NULL) return 1; // read error
if(strlen(s) == 0) return 2; // other read error
if(s[strlen(s)-1] !='\n') return 3; // buffer overflow error
s[strlen(s)-1]=0; // replace newline with null
return 0;
}
if(Getsafestring(p.name,sizeof(p.name))) exit(1);
if(scanf("%d", &p.by) != 1) exit(1);
if(getsafestring(p.p_id,sizeof(p.p_id))) exit(1);
if(getsafestring(p.cel,sizeof(p.cel))) exit(1);

Count number of spaces and words in an integer [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
I'm trying to write a C program that counts the number of words and spaces in a given string. Here's what I have so far:
#include <stdio.h>
int main()
{
int i, spaces;
char a[30];
printf("enter the string");
scanf("%s", a);
for(i=0 ; a[0]!="\0" ; i++
{
if (a[i]=' ')
{
spaces++;
}
}
printf("Number of spaces is %d", spaces);
printf("Number of words is %d", spaces + 1);
}
It gives me a weird error at 9:19. Help would be much appreciated.
Updated:
#include <stdio.h>
int main()
{
int i,spaces;
char a[100];
printf("enter the string\n");
scanf("%s",a);
for(i=0 ; a[i]!='\0' ; i++)
{
if (a[i]==' ')
{
spaces++;
}
}
printf("the no. of spaces in the string is %d\n",spaces);
printf("the no. of words in the string is %d\n",spaces+1);
}
Now doesn't metter what string I input, it'll say there's 0 spaces and 1 word. Why is this?
The first think, you forgot the for closing parenthese. And the condition expression you must use '\0' instead of "\0". Also you need to check a[i] not a[0].
for(i = 0; a[i] != '\0'; i++)
{
if (a[i] == ' ')
{
spaces++;
}
}
Note that you should initialize spaces to 0 before using it.
spaces = 0;
Update:
Another thing, to input a full string with spaces use fgets() instead of scanf:
fgets(a, 100, stdin);
The first argument is your string, the second is the maximum number of characters to input and the third is the stream from where you will get the input: stdin in your case wich is the standard input stream.
Live exemple: https://eval.in/101504
In C, a char[] literal is written with double quotes ("), and a char literal is written with single quotes ('). Change "\0" to '\0'. This is the source of your "weird error."
The bracket syntax is syntactic sugar for dereferencing an offset pointer to a contiguous block of memory, based on what you declared it would contain. Maybe a crude diagram could help? This is a depiction of a char[5]. It's a pointer block of memory that can hold 5 chars and a null terminator.
['h']['e']['l']['l']['o']['\0']
^
a // you called your char[] a, so I did too
A char* is a pointer to a char. So you could also call a a char*. Say you wanted to access the first 'l' in the char[]... well, you'd have to point to the address exactly 2*sizeof(char) ahead. a[2] is the same thing as *(a+(2*sizeof(char))).
So when you dereferenced your char* you got a char, obviously. But "\0" is a char[] literal (i.e. a string) and you can't compare the two.
Other problems: you should close the parentheses on your for loop, and make your comparison a[i]!='\0' (that way you are checking each char as you iterate through the char[]. I think you also meant to check if(a[i]==' '). Otherwise you will be clearing out your string with spaces :)
A little tip for going forward: if you are comparing a variable to a literal, put the literal first so you're less likely to make typos like that. e.g. ' '==a[i]. If you used = instead you would get an error (because you'd be trying to assign something to a literal).
Edit: since you updated your code, I'd like to point out that you should probably initialize spaces to be 0.
Now I won't take credit for this, but in case someone in the future is reading, fgets is what you're looking to use instead of scanf. Thanks to drch for pointing this out.
You're always comparing a[0] to '\0' so your loop continues endlessly, compare it to a[i].
One more thing is that "\0" is a string (char*), you need to compare it to '\0' which is a char.
The reason you're getting 0 and 1 is because of the way you're using scanf. Using scanf with %s just reads the first string that does not include white space. So if you typed
"The fox jumped over the moon"
The output will be 0 spaces and 1 word. This is because scanf(%s, a) will just put "The" into a and will ignore the rest of the string.
http://www.cplusplus.com/reference/cstdio/scanf/
You can use scanf("[^\r\n]", a). I believe that should get you what you want (or close to it anyway).

strcmp() thinks that strings arent equal.. but are they? [duplicate]

This question already has answers here:
strcmp on a line read with fgets
(6 answers)
Closed 7 years ago.
For unknown reason, result of running my C program is quite unexpected. I think that it has to be some kind of a beginner mistake, however I can't find out really, where is it.
#include <stdio.h>
#include <string.h>
int main()
{
char string1[50];
char string2[50];
int compare;
puts("Enter two strings: ");
fgets(string1, strlen(string1)+1, stdin);
fgets(string2, strlen(string2)+1, stdin);
compare=strcmp(string1, string2); /* usage of extra variable makes the code more readable but wastes more memory */
printf("%d: ",compare);
if (compare<0) puts("First string is lesser");
else if (compare>0) puts ("First string is bigger");
else puts("Strings are equal");
return 0;
}
And on testing:
Enter two strings:
heheisntthisalongstring
heheisntthisalongstring
1: First string is bigger
------------------
(program exited with code: 0)
Press return to continue
Shouldn't those strings be equal?
fgets(string1, strlen(string1)+1, stdin);
fgets(string2, strlen(string2)+1, stdin);
These are wrong. string1 and string2 are not initialized, and strlen just counts the number of bytes, till hitting \0. In this case, strlen could return any (random non-negative) number.
Use sizeof, instead of strlen here.
Here
char string1[50];
char string2[50];
you dont initialise them, so your initial calls to strlen are unreliable as they are looking for the first null char they find after the start of the array. This could be anywhere and the results of the call may or may not be a true reflection on the size - you just cant rely at all on the results.
string1 is not memset to 0, So strlen(string1) value will not give the expected value (50). strlen will counts the character till it reaches \0. So it may leads to crash also(an undefined behaviour).
Better memset both string1 and string2 like below.
char string1[50] = {0};
char string2[50] = {0};
and also use sizeof operator to get the value 50.
fgets(string1, sizeof(string1), stdin);
fgets(string2, sizeof(string2), stdin);
or else directly go for scanf
scanf("%s", string1);
scanf("%s", string2);
Here have a look at this-strlen
Although the code you are using is not good but you can still get your expected answer by using strncmp giving the 3rd parameter the strlen of a common string variable. Just for fun.
Always initialize your variables or they can lead your application to crash. You can see the examples here- strncmp

Resources