Initializing a variable causing printf to stop working [closed] - c

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions must demonstrate a minimal understanding of the problem being solved. Tell us what you've tried to do, why it didn't work, and how it should work. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
int get_max_horizantal()
{
char str[2];
char strb[2]; //Everything works well unless I put this
extern char shit[1200];
int x,number;
while((3*x+1)<1200)
{
if(number%17==0 && number!=0)
{
x+=2;
number=-1;
}
str[0]=shit[3*x];
str[1]=shit[3*x+1];
int val1=atoi(str);
printf("%d\n",val1);
x++;
number++;
}
}
Ok so this is something I don't get at all...The whole function works well but when I put this
char strb[2];
printf doesn't print anything and there are no compile errors or warnings...
This time I really need help on this one...Thanks in advance.

If you want to use atoi on a char array, you must put a null terminator at the end.
Adding things to the stack changing the behaviour often means you have walked off the end of some memory.
Make str bigger and add the null at the end:
char str[3];
str[2] = 0;

atoi wants a proper string. What you pass it is not a proper string since it's not nul-terminated. This leads to undefined behavior which in your case presents itself as seemingly unrelated change making things work or not work.

The atoi(3) function expects a null-terminated string, that is an array of char containing a zero byte (which conventionally terminates the string).
You should give at least 3 characters to str and zero them before filling them, either using memset or explicitly clearing the last byte:
char str[3];
/* possible alternative:
memset (str, 0, sizeof(str)); // the compiler will optimize that...
*/
str[0] = shit[3*x];
str[1] = shit[3*x+1];
str[2] = (char)0;
Please take the habit of enabling all warnings and debugging information at compile time (e.g. compile with gcc -Wall -g on Linux), and learn how to use the debugger (gdb on Linux).
I'm sure that your compiler is able to warn you that x and number are not initialized, and you should fix that:
int x=0, number=0;
As a rule of thumb, improve your source code till no warnings are given by your compiler (with all warnings requested by e.g. -Wall and possibly even also -Wextra if using gcc). Then use a debugger to debug your code: on Linux the p or print, s or step, d or display, bt or backtrace commands of gdb should become familiar to you.
Consider using snprintf(3) (but don't use the deprecated and unsafe sprintf).
Learn about Undefined Behavior. Your program might apparently happens to work (by lack of luck) but be buggy.

Related

Would you please explain why I am getting error in this testcase 99? [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 11 months ago.
Improve this question
https://codeforces.com/contest/61/problem/A
Here in the testcase 99 of this I am experiencing an error which I am not getting in codeblocks. What I have identified is, after printing the needed output correctly, some 1s are being printed. I am not getting the fact why these 1s are being printed.
Here is my code:
#include<stdio.h>
#include<string.h>
int main()
{
char x[100],y[100];
scanf("%s%s",&x,&y);
for(int i=0;i<strlen(x);i++)
{
if(x[i]==y[i])
{
printf("0");
}
else
{
printf("1");
}
}
return 0;
}
Image: Error in testcase 99
That use of scanf is dangerous. It can lead to a buffer-overflow, that will produce undefined behaviour (behaviour may be different on different platforms, or even each time that you run the program).
Turn on compiler warnings. Use a good static analysis tool, or better use a safer language such as golang. Then use scanf format strings that prevent buffer overrun. On gcc the option -Wall will turn on this warning. You may also want to turn on some other warnings, or turn up the level to be more strict (especially for new code).
You have some issues in your code:
char x[100],y[100];
scanf("%s%s",&x,&y);
The type of second and third argument for scanf is not correct. They may have correct value, but strictly speaking they are wrong.
You need a char* but you provide a char (*)[]. You should just use x,y without the &.
Also you do not take care about potential buffer overflows.
To avoid buffer overflows, you should add a length limit to your format specifier. It must be one less than the size of your arrays.
Also you are required to deal with numbers up to 100 digits. That does not fit into your buffers.
If you need to handle strings of length 100, your arrays must have size 101.
You don't do this. If you get a string that is too long for one of your arrays, you will probably overflow into the next buffer losing the terminator byte.
That said, the 2 lines above should look like this:
char x[101],y[101];
scanf("%100s%100s", x, y);
Additionally you should always check return value of scanf and other IO functions.
To improve performance a bit, you should also not call strlen in each iteration of the loop. Instead you should call it once before the loop and store the value to use it in the loop condition.

C language beginner [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I'm learning C language following Youtube video and I've got couple of questions.
I typed these below in Xcode
#include<stdio.h>
int main() // 1. why do we have to use this line?
{
char food[] = "tuna";
printf("the best food is %s",food);
strcpy(food,"bacon"); // error here
return 0;
}
When I typed these all, the error come out saying " implicity declaring library function 'strcpy' with type 'char*(char*,const char*)'"
I have no idea what this mean and why it happened? Sorry to bother with question guys but I need your help. Thank you
C is a super great language to learn but because of how low level it is in comparison to python, javascript, etc. There are many manual tasks you need to do including memory management.
But before we get into that, your initial problem is not including the string.h header. Once you include that header, you'll actually get Segmentation Fault.
Below is the explanation on why you'll get the Segmentation Fault.
So when you defined:
char food[] = "tuna"
C created char array with 5 bytes. Why 5? because all strings end with a NULL byte ('\0').
So your string in memory looks like "tuna\0".
Side note:
The importance of the NULL byte is to signify the end of a string. This is super important when you are using a function like printf. Because when printing a string, printf will look for the NULL byte to stop printing.
So this char array has the max size of 5 bytes, 1 being a null byte, so just 4 bytes (chars) of writeable memory.
Then you try to copy the word "bacon" into your 5 byte array.
So strcpy tries to copy the b, then the c, then the o, then the n, then when it tries to terminate the string with a NULL byte, it will seg fault because you're trying to access a byte of memory you don't have access to.
So in order to fix your issue, you could try to strcpy a string that is the same length or shorter than your original string. Or you can look into something like strdup and use pointers.
That code will look like:
#include <stdio.h>
#include <string.h>
int main()
{
char *food = "tuna";
printf("the best food is %s\n",food);
food = strdup("bacon");
printf("the best food is %s\n",food);
return 0;
}
Hope this helps!
I suggest you as exercise to explain me the behavior of this code. You have to understand how "strings" are managed by the C language into the memory.
The code I post below is not right, contains a violation of the space allocated for the variable food. In this case this code doesn't generate a Segmentation Fault, but It might generate such a error!
If you compile the code below with gcc -Wall --pedantic -std=c99 prgname.c
, the compiler doesn't signal warnings nor error, but the code is NOT RIGHT.
PAY ATTENTION! :)
#include <stdio.h>
#include <string.h>
int main() // 1. why do we have to use this line?
{ // --- 'cause is a standard!!! :)
char food[] = "tuna";
char b[]="prova";
printf("the best food is %s - %s - food-size %u\n",food,b,(unsigned int)sizeof(food));
strcpy(food,"fried or roasted bacon"); // error here
printf("the best food is %s - %s - food-size %u\n",food,b,(unsigned int)sizeof(food));
return 0;
}
We have to use main(),this is the function through which execution of C program starts.
For using strcpy()(A predefined function) you need to declare it first. and its declaration is present in string.h so just #include<string.h>
This will resolve your problem.implicit declaring library function 'strcpy' with type'char*(char*,const char*)``
There is one more problem when you declare
char food[]="tuna";
you get only 5 bytes allocated for you,four for character and one more for NULL. When you will try putting baconin it (using strcpy()),which is 6 bytes long. It will cause compiler to create segmentation fault.

Strings behvior on C

I want to understand a number of things about the strings on C:
I could not understand why you can not change the string in a normal assignment. (But only through the functions of string.h), for example: I can't do d="aa" (d is a pointer of char or a array of char).
Can someone explain to me what's going on behind the scenes - the compiler gives to run such thing and you receive segmentation fault error.
Something else, I run a program in C that contains the following lines:
char c='a',*pc=&c;
printf("Enter a string:");
scanf("%s",pc);
printf("your first char is: %c",c);
printf("your string is: %s",pc);
If I put more than 2 letters (on scanf) I get segmentation fault error, why is this happening?
If I put two letters, the first letter printed right! And the string is printed with a lot of profits (incorrect)
If I put a letter, the letter is printed right! And the string is printed with a lot of profits and at the end something weird (a square with four numbers containing zeros and ones)
Can anyone explain what is happening behind?
Please note: I do not want the program to work, I did not ask the question to get suggestions for another program, I just want to understand what happens behind the scenes in these situations.
Strings almost do not exist in C (except as C string literals like "abc" in some C source file).
In fact, strings are mostly a convention: a C string is an array of char whose last element is the zero char '\0'.
So declaring
const char s[] = "abc";
is exactly the same as
const char s[] = {'a','b','c','\0'};
in particular, sizeof(s) is 4 (3+1) in both cases (and so is sizeof("abc")).
The standard C library contains a lot of functions (such as strlen(3) or strncpy(3)...) which obey and/or presuppose the convention that strings are zero-terminated arrays of char-s.
Better code would be:
char buf[16]="a",*pc= buf;
printf("Enter a string:"); fflush(NULL);
scanf("%15s",pc);
printf("your first char is: %c",buf[0]);
printf("your string is: %s",pc);
Some comments: be afraid of buffer overflow. When reading a string, always give a bound to the read string, or else use a function like getline(3) which dynamically allocates the string in the heap. Beware of memory leaks (use a tool like valgrind ...)
When computing a string, be also aware of the maximum size. See snprintf(3) (avoid sprintf).
Often, you adopt the convention that a string is returned and dynamically allocated in the heap. You may want to use strdup(3) or asprintf(3) if your system provides it. But you should adopt the convention that the calling function (or something else, but well defined in your head) is free(3)-ing the string.
Your program can be semantically wrong and by bad luck happening to sometimes work. Read carefully about undefined behavior. Avoid it absolutely (your points 1,2,3 are probable UB). Sadly, an UB may happen to sometimes "work".
To explain some actual undefined behavior, you have to take into account your particular implementation: the compiler, the flags -notably optimization flags- passed to the compiler, the operating system, the kernel, the processor, the phase of the moon, etc etc... Undefined behavior is often non reproducible (e.g. because of ASLR etc...), read about heisenbugs. To explain the behavior of points 1,2,3 you need to dive into implementation details; look into the assembler code (gcc -S -fverbose-asm) produced by the compiler.
I suggest you to compile your code with all warnings and debugging info (e.g. using gcc -Wall -g with GCC ...), to improve the code till you got no warning, and to learn how to use the debugger (e.g. gdb) to run your code step by step.
If I put more than 2 letters (on scanf) I get segmentation fault error, why is this happening?
Because memory is allocated for only one byte.
See char c and assigned with "a". Which is equal to 'a' and '\0' is written in one byte memory location.
If scanf() uses this memory for reading more than one byte, then this is simply undefined behavior.
char c="a"; is a wrong declaration in c language since even a single character is enclosed within a pair of double quotes("") will treated as string in C because it is treated as "a\0" since all strings ends with a '\0' null character.
char c="a"; is wrong where as char c='c'; is correct.
Also note that the memory allocated for char is only 1byte, so it can hold only one character, memory allocation details for datatypes are described bellow

C buffer overflow only when way out of range

Consider next test program:
char a[10];
strcpy(a, "test");
for(int i=0; i<3; i++) {
char b[2];
strcpy(b, "tt");
strcat(a, b);
}
printf("%d %d %s\n", strlen(a), sizeof(a), a);
Output: 10 10 testtttttt.
Everything seems ok.
If i<7 the buffer is overflow, however there is no error. Output: 18 10 testtttttttttttttt. Program seems to be working.
If i<11 then we see an error "stack smashing detected"...
Why is that program doesn't prompt an error when i<7 ?
What you are doing is undefined behaviour. Anything could happen. What you saw is just one possible outcome, that some automatic tool detected it quite late instead of instantly. Your code is wrong, any assumption what should happen is wrong, and asking for a "why" is pointless. With a different compiler, or with different compiler settings, or on a different day, the outcome could be completely different.
By the way, there is a buffer overflow when i = 0 since you are trying to copy two chars and a trailing zero byte into a buffer that only has space for two chars.
If i<7 the buffer is overflow, however there is no error. Output: 18
10 testtttttttttttttt. Program seems to be working.
The reason is because its an undefined behavior. You can expect any value to appear since you are accessing an array out of its limits
You may check Valgrind for these scenarios
Your buffer variable is only allowing 10 characters, your argument is 11, increase your buffer to support your argument.
char a[10];
The error which you are getting i.e, Stack Smashing, that is a protection mechanism used by gcc to check buffer overflow errors.
You are asking why there is no Error:
The buffer overflow detection is a feature to help you, but there's absolutely no guaranty that it'll detect buffer overflows.

I am trying to do a program that picks a vowel from the user input [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char *v= "a";
char *o='e';
char * w='i';
char *e='o';
char *l='u';
char *u[1];
printf ("please enter your character\n");
scanf ("%c",& u);
if (u == v){
puts("the character is it a vowel\n");
}
if (u == o) {
puts("the character is it a vowel\n");
}
else
puts("the character is a constant\n");
system("PAUSE");
return 0;
}
i need help in getting the right answer in finding a vowel from the user input.
First of all, shame on you for ignoring all of the compiler warnings you certainly received. They are there to help prevent you from doing "stupid things."
And why all this nonsense? This is the first of the "stupid things" the compiler is trying to tell you about.
char *v= "a";
char *o='e'; // invalid - Initializing a pointer to a constant 'e' (101).
char * w='i'; // invalid
char *e='o'; // invalid
char *l='u'; // invalid
Are you familiar with how pointers work? If not, I suggest you do some reading and understand them.
The first line makes sense - you're making a string and pointing char* v to that string.
But there's really no point in using pointer for those characters - or even variables at all. Just compare them directly:
char my_character;
if (my_character == 'a') {
// do something
}
And as for reading the character, again, you're using pointers when it doesn't make sense:
char *u[1]; // why?
Instead, just define a single char variable. Now, go look at the documentation for scanf. Giving it a format string of "%c" means, "I want to read just one character". Then, you need to tell where scanf to put it. You do this by passing it the "address of" the variable you want to store it in. You do this with (unsurprisingly!) the address of operator &.
char input_character;
scanf("%c", &input_character);
Armed with this information, you should be able to complete your work. Next, I suggest you look into the switch statement.
Finally, you must use consistent formatting (indentation, spacing) and use meaningful variable names, if you have any desire of ever being taken seriously as a programmer. Spelling out "vowel" for your pointless variables may be "cute" but it's total nonsense.
Most importantly, you should never write a single line of code, unless you understand exactly what it does. If you do this, then do not go asking anyone for help (especially not StackOverflow). If you can't explain what your code is doing (or at least what you think it's supposed to do), then you don't deserve for your program to work.

Resources