'Scanf' for a String - Program crashing? - c

Why is this crashing when I input the string? I don't think I'm reading in the string right but the program gives me an error on the first 'scanf.' The program should be correct but this is C not C++. Most help that I could find was for C++.
//Andrei Shulgach
//April 27th, 2015
/*A string is a palindrome if it can be read forward and backward with the same
meaning. Capitalizations and spacing are ignored.*/
#include <stdio.h>
#include <stdlib.h>
int newStrCmp (const char *string1, const char *string2);
int main()
{
//Local Declarations
int dummy, value;
char string1[100],string2[100];
printf("Please enter the 1st string: ");
scanf_s("%99s", string1[100]);
printf("\nPlease enter the 2nd string: ");
scanf_s("%99s", string2[100]);
//Call Function and get value
value = newStrCmp(string1, string2);
if (value == 0)
printf("The strings are equal.\n");
else
printf("The strings are not equal.\n");
scanf_s("%d",&dummy);//Keep Window Open
return 0;
}
int newStrCmp (const char *string1, const char *string2)
{
//Local Declarations
int value = 0;
while (string1[value] == string2[value])
{
if (string1[value] == '\0' || string2[value] == '\0')
break;
value++;
}
if (string1[value] == '\0' && string2[value] == '\0')
return 0;
else
return -1;
}

You must enable all compiler warnings that you can get from your compiler; the above code shouldn't have compiled.
This:
scanf_s("%99s", string1[100]);
invokes undefined behavior since it indexes outside the 100-character string1 array. Remember that C arrays are indexed from 0. It also fails to comply with scanf_s()'s requirement that the size be specified for all string conversions.
It then probably1 causes more undefined behavior, when scanf_f() interprets a single character as a buffer address where input is to be stored (assuming the call happens, of course).
This is not valid code.
It should simply pass the address of the first character in the array:
scanf_s("%99s", string1, sizeof string1);
Here, string1 is the same as &string1[0]; the name of an array evaluates to the address of its first element in many contexts. We then use sizeof string1 as the third argument to specify the size of the string1 buffer, which is required.
1 You cannot reason about what happens after undefined behavior has happened with any certainty.

The issue is you are 'scanf'ing into index 100 of your length 100 buffer, i.e. out-of-bounds.
scanf_s("%99s", string1);
Also your comparison would be safer as a for loop that ensures value is less than 100, rather than a while loop.
In the future, please include the error message.

Related

How on earth to use char and if statements?

I'm a rookie programmer trying to run a simple code on VS code.
#include<stdio.h>
int main()
{
char* a;
printf("Enter a char");
scanf("%s",&a);
if (a = "yes")
{
printf("Number is 30");
}
else if (a = "no")
{
printf("Number is 50");
}
else{
printf("oops");
}
return 0;
}
I guess looking at the code you guys can figure out what I'm trying to do, if the user enters "yes", a specific sentence need to be displayed and similarly for "no".
The problem here is whatever I write in the input, it will always print the first statement, "Number is 30". I've tried running similar codes but ended up with the same output.
If possible, please explain me how to use char,strings,arrays with if-else statements.
There are several misunderstandings in the posted code.
First there is a misunderstanding of char versus string. A char is for instance a single letter, a single special character like ., ;, etc. (see note1) while a string is a serie of chars. So
'y' is a char
"yes" is a string
You print "Enter a char" but from the code it's obvious that you really want "Enter a string".
This leads to the next problem. To input a string using scanf you need to pass a "pointer to char". Your code pass "a pointer to pointer to char" due to the &. Further the passed pointer must point to some memory. So you need:
char a[10]; // Make it an array of char so that it can hold a string
printf("Enter a string, max 9 characters");
scanf("%9s", a); // No & before a and width specifier used to avoid buffer overflow
Now this part
if (a = "yes")
is not the way to compare two strings in C. For that you need the function strcmp - like:
if (strcmp(a, "yes") == 0)
Putting it together it's like:
int main()
{
char a[10];
printf("Enter a string, max 9 characters");
scanf("%9s", a);
if (strcmp(a, "yes") == 0){
printf("Number is 30");
}
else if (strcmp(a, "no") == 0)
{
printf("Number is 50");
}
else
{
printf("oops");
}
return 0;
}
That said, I don't understand why you print stuff like: "Number is 30" but that's kind of irrelevant here.
note1: The type char is actually an integer type, i.e. a number, but the common use is to map these numbers to characters using ASCII encoding.
There are different ways to initialize a variable to access C string.
char *char_ptr = "Hello";
This initializes char_ptr to point to the first character of the read-only string "Look Here".A C string initialized through a character pointer cannot be modified. When a C string is initialized this way, trying to modify any character pointed to by char_ptr is undefined behaviour. An undefined behaviour means that when a compiler encounters anything that triggers undefined behaviour, it is allowed to do anything it seems appropriate.
A more convenient way to define strings that can be modified is to use:
char str[];
This way you can modify any character in the C string
p.s you also need to use strcmp() for the if statement
You can take string input in C using
scanf(ā€œ%sā€, str);
And to compare the string you need to use:
strcmp(str1, "yes");

Error in string do while [duplicate]

This question already has answers here:
How do I properly compare strings in C?
(10 answers)
Closed 5 years ago.
char str[6];
do
{
printf("Enter the string you wanna check:");
scanf("%s", str);
}
while(str != "exit");
Why does this not work?
str will never equal "exit", because you're comparing the addresses of two different sections of memory. You probably want to compare the contents of the strings, for which there is a function strcmp().
"exit" is a char[5] generated by the compiler at some address in the data segment. This address is definitely different from the address of str, as two different objects cannot occupy the same location in memory.
The != operator between expressions of type char[] compares two pointers. These two pointers are the address of "exit" and the address of str, which, as I have already explained, will never be equal.
So, the expression str != "exit" will never evaluate to true. Which brings us to another point: your compiler should have issued a warning about this condition being always false. Which means that you are trying to program without -Wall. Don't do this, you are never going to get very far. Always use the highest warning level, and when you see warnings, always fix them.
To correct the problem, do as user3121023 suggested in a comment, and use strcmp() to compare strings.
The short answer is: it does not work because you must use strcmp(str, "exit") to compare the strings and loop for as long as the return value of strcmp() is not 0.
The long answer is: there are more problems in this little code fragment:
The array into which you read a word is very short and you do not limit the number of characters scanf() is likely to store there. Any user input longer than 5 non space characters will cause undefined behavior.
You do not check the return value of scanf(). A premature end of file, such as redirecting input from an empty file, will cause an infinite loop.
Here is how the code can be written in a safer way:
#include <stdio.h>
int main(void) {
char str[80];
for (;;) {
printf("Enter the string you wanna check:");
if (scanf("%79s", str) != 1 || strcmp(str, "exit") == 0)
break;
}
return 0;
}
As suggested above, use strcmp from the <string.h> header file.
char str[6];
do {
printf("Enter the string you wanna check:");
scanf("%s", str);
} while(!strcmp(str, "exit"));
Try :
#include <stdio.h>
#include <string.h>
int main() {
char str[6];
do
{
printf("Enter the string you wanna check:");
scanf("%s", str);
}
while(strcmp(str, "exit") != 0);
return 0;
}

Why is strlen causing a segmentation fault in C?

(Warning) Yes this is a part of an assignment I am working on, but I am completely desperate at this point and NO I am not looking for you guys to solve it for me, but any hint would be much appreciated!(/Warning)
I am pretty much trying to make an interactive menu, the user is meant to input an expression (For example "5 3 +") and the program should detect that it's in postfix notation, unfortunately I have been getting segmentation fault errors and I suspect they have something to do with the use of the strlen function.
EDIT: I was able to make it work, first the char expression[25] = {NULL}; line
becomes char expression[25] = {'\0'};
And when calling the determine_notation function I removed the [25] from the array I am passing like so:
determine_notation(expression, expr_length);
Also the input[length] part I changed to input[length-2] since like mentioned in a previous comment, input[length] == '\0' and input[length--] == '\n'.
All in all thanks for all the help!
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int determine_notation(char input[25], int length);
int main(void)
{
char expression[25] = {NULL}; // Initializing character array to NULL
int notation;
int expr_length;
printf("Please enter your expression to detect and convert it's notation: ");
fgets( expression, 25, stdin );
expr_length = strlen(expression[25]); // Determining size of array input until the NULL terminator
notation = determine_notation( expression[25], expr_length );
printf("%d\n", notation);
}
int determine_notation(char input[25], int length) // Determines notation
{
if(isdigit(input[0]) == 0)
{
printf("This is a prefix expression\n");
return 0;
}
else if(isdigit(input[length]) == 0)
{
printf("This is a postfix expression\n");
return 1;
}
else
{
printf("This is an infix expression\n");
return 2;
}
}
You probably got a warning explaining that you are converting a char to a pointer in this call:
expr_length = strlen(expression[25]);
// ^^^^
This is the problem - your code is referencing a non-existent element past the end of the array (an undefined behavior) and tries to pass it to strlen.
Since strlen takes a pointer to the beginning of the string, the call needs to be
expr_length = strlen(expression); // Determining size of array input until the NULL terminator

How to correctly input a string in C

I am currently learning C, and so I wanted to make a program that asks the user to input a string and to output the number of characters that were entered, the code compiles fine, when I enter just 1 character it does fine, but when I enter 2 or more characters, no matter what number of character I enter, it will always say there is just one character and crashes after that. This is my code and I can't figure out what is wrong.
int main(void)
{
int siz;
char i[] = "";
printf("Enter a string.\n");
scanf("%s", i);
siz = sizeof(i)/sizeof(char);
printf("%d", siz);
getch();
return 0;
}
I am currently learning to program, so if there is a way to do it using the same scanf() function I will appreciate that since I haven't learned how to use any other function and probably won't understand how it works.
Please, FORGET that scanf exists. The problem you are running into, whilst caused mostly by your understandable inexperience, will continue to BITE you even when you have experience - until you stop.
Here is why:
scanf will read the input, and put the result in the char buffer you provided. However, it will make no check to make sure there is enough space. If it needs more space than you provided, it will overwrite other memory locations - often with disastrous consequences.
A safer method uses fgets - this is a function that does broadly the same thing as scanf, but it will only read in as many characters as you created space for (or: as you say you created space for).
Other observation: sizeof can only evaluate the size known at compile time : the number of bytes taken by a primitive type (int, double, etc) or size of a fixed array (like int i[100];). It cannot be used to determine the size during the program (if the "size" is a thing that changes).
Your program would look like this:
#include <stdio.h>
#include <string.h>
#define BUFLEN 100 // your buffer length
int main(void) // <<< for correctness, include 'void'
{
int siz;
char i[BUFLEN]; // <<< now you have space for a 99 character string plus the '\0'
printf("Enter a string.\n");
fgets(i, BUFLEN, stdin); // read the input, copy the first BUFLEN characters to i
siz = sizeof(i)/sizeof(char); // it turns out that this will give you the answer BUFLEN
// probably not what you wanted. 'sizeof' gives size of array in
// this case, not size of string
// also not
siz = strlen(i) - 1; // strlen is a function that is declared in string.h
// it produces the string length
// subtract 1 if you don't want to count \n
printf("The string length is %d\n", siz); // don't just print the number, say what it is
// and end with a newline: \n
printf("hit <return> to exit program\n"); // tell user what to do next!
getc(stdin);
return 0;
}
I hope this helps.
update you asked the reasonable follow-up question: "how do I know the string was too long".
See this code snippet for inspiration:
#include <stdio.h>
#include <string.h>
#define N 50
int main(void) {
char a[N];
char *b;
printf("enter a string:\n");
b = fgets(a, N, stdin);
if(b == NULL) {
printf("an error occurred reading input!\n"); // can't think how this would happen...
return 0;
}
if (strlen(a) == N-1 && a[N-2] != '\n') { // used all space, didn't get to end of line
printf("string is too long!\n");
}
else {
printf("The string is %s which is %d characters long\n", a, strlen(a)-1); // all went according to plan
}
}
Remember that when you have space for N characters, the last character (at location N-1) must be a '\0' and since fgets includes the '\n' the largest string you can input is really N-2 characters long.
This line:
char i[] = "";
is equivalent to:
char i[1] = {'\0'};
The array i has only one element, the program crashes because of buffer overflow.
I suggest you using fgets() to replace scanf() like this:
#include <stdio.h>
#define MAX_LEN 1024
int main(void)
{
char line[MAX_LEN];
if (fgets(line, sizeof(line), stdin) != NULL)
printf("%zu\n", strlen(line) - 1);
return 0;
}
The length is decremented by 1 because fgets() would store the new line character at the end.
The problem is here:
char i[] = "";
You are essentially creating a char array with a size of 1 due to setting it equal to "";
Instead, use a buffer with a larger size:
char i[128]; /* You can also malloc space if you desire. */
scanf("%s", i);
See the link below to a similar question if you want to include spaces in your input string. There is also some good input there regarding scanf alternatives.
How do you allow spaces to be entered using scanf?
That's because char i[] = ""; is actually an one element array.
Strings in C are stored as the text which ends with \0 (char of value 0). You should use bigger buffer as others said, for example:
char i[100];
scanf("%s", i);
Then, when calculating length of this string you need to search for the \0 char.
int length = 0;
while (i[length] != '\0')
{
length++;
}
After running this code length contains length of the specified input.
You need to allocate space where it will put the input data. In your program, you can allocate space like:
char i[] = " ";
Which will be ok. But, using malloc is better. Check out the man pages.

Checking equality of a string in C and printing an answer [duplicate]

This question already has answers here:
C Strings Comparison with Equal Sign
(5 answers)
Closed 9 years ago.
i've written some simple code as an SSCCE, I'm trying to check if string entered is equal to a string i've defined in a char pointer array, so it should point to the string and give me a result. I'm not getting any warnings or errors but I'm just not getting any result (either "true" or "false")
is there something else being scanned with the scanf? a termination symbol or something? i'm just not able to get it to print out either true or false
code:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#define LENGTH 20
//typedef char boolean;
int main(void)
{
const char *temp[1];
temp[0] = "true\0";
temp[1] = "false\0";
char var[LENGTH];
printf("Enter either true or false.\n");
scanf("%s", var);
if(var == temp[0]) //compare contents of array
{
printf("\ntrue\n");
}
else if(var == temp[1]) //compare contents of array
{
printf("\nfalse\n");
}
}
const char *temp[1];
This defines tmp an array that can store 1 char* element.
temp[0] = "true\0";
Assigngs to the first element. This is okay.
temp[1] = "false\0";
Would assign to the second element, but temp can only store one. C doesn't check array boundaries for you.
Also not that you don't have to specify the terminating '\0' explicitly in string literals, so just "true" and "false" are sufficient.
if(var == temp[0])
This compares only the pointer values ("where the strings are stored"), not the contents. You need the strcmp() function (and read carefully, the returned value for equal strings might not be what you expect it to be).
Use strcmp for comparing strings:
#include <stdio.h>
int main(void)
{
const int LENGTH = 20;
char str[LENGTH];
printf("Type \"true\" or \"false\:\n");
if (scanf("%19s", str) != 1) {
printf("scanf failed.");
return -1;
}
if(strcmp(str, "true") == 0) {
printf("\"true\" has been typed.\n");
}
else if(strcmp(str, "false") == 0) {
printf("\"false\" has been typed.\n");
}
return 0;
}
and also note that:
string literals automatically contain null-terminating character ("true", not "true\0")
const int LENGTH is better than #define LENGTH since type safety comes with it
"%19s" ensures that no more than 19 characters (+ \0) will be stored in str
typedef char boolean; is not a good idea
unlikely, but still: scanf doesn't have to succeed
and there is no #include <iostream> in c :)
== checks for equality. Let's see what you're comparing.
The variable var is declared as a character array, so the expression var is really equivalent to &var[0] (the address of the first character in the var array).
Similarly, temp[0] is equivalent to &temp[0][0] (the address of the first character in the temp[0] array).
These addresses are obviously different (otherwise writing var would automatically write temp[0] as well), so == will always return 0 for your case.
strcmp, on the other hand, does not check for equality of its inputs, but for character-by-character equality of the arrays pointed to by its inputs (that is, it compares their members, not their addresses) and so you can use that for strings in C. It's worth noting that strcmp returns 0 (false) if the strings are equal.

Resources