#include <stdio.h>
int main(void) {
int n,i;
int str[n];
scanf("%d\n",&n);
for(i=0;i<=n;i++)
{
scanf("%d",&str[i]);
printf("%d th %d\n",i,n);
}
return 0;
}
Input:
10
8 9 2 1 4 10 7 6 8 7
Output:
0 th 10
1 th 10
2 th 10
3 th 10
4 th 10
5 th 10
6 th 10
7 th 6
Why is 6 in the output?
This is really strange code with undefined behavior. What do you expect this:
int n; // No value!
int str[n];
To do? You get an array whose length is unknown since n has no value at the point of the str declaration.
If you expected the compiler to "time-travel" back to the str[n] line magically when n is given a value by scanf(), then ... that's not how Co works, and you should really read up on the language a bit more. And compile with all warnings you can get from your environment.
As an extra detail, even if it were fixed so that n had a value, the for loop overruns the array and gives you undefined behavior again.
For an array of size m, the loop header should read
for (size_t i = 0; i < m; ++i)
Since indexing is 0-based, you cannot index at m, that's outside the array.
In your code
int n,i;
int str[n];
you're using n while it has indeterminate value, unitialized. It invokes undefined behavior.
To elaborate, n being an automatic local variable, unless initialized explicitly, contains indeterminate value.
Solution: You need to define int str[n]; after you has taken the value from user (and sanitized).
After that, there's once more issue, your loop runs off-by-one for the array. C uses 0-based array indexing, so, for an array of size n, the valid indexes will be 0 to n-1. You loop construct should be
for(i=0; i<n; i++)
The value for the size of the string str[] is not yet defined. You need to have initialized this value before declaring a string/array.
If you're using gcc to compile, try including the -Wall flag in your compile line to catch errors like this.
Related
I want to print the value as well as its type
Input:
1
3
5
78
10
Output:
Odd 1
Odd 3
Odd 5
Even 78
Odd 11
#include <stdio.h>
int main()
{
int a[4],b,c;
for(b=0 ; b<=4 ; b++)
{
scanf("%d",&a[b]);
}
for (c=0 ; c<=4 ; c++)
{
switch (a[c]%2)
{
case 0 :
printf ("Even %d\n",a[c]);
break;
case 1 :
printf ("Odd %d\n",a[c]);
break;
}
}
return 0;
}
Why is the last output Odd 11 instead of Even 10?
You only have to change the declaration of a[4] into a[5] for having a correct program. The boundaries of the iterations are correct.
What happens when you run your code is that the four first input values go into the array a[4] and the fifth one into the variable b which is allocated immediately behind the array, in your case. This is a programming error and gives unpredictible results, depending on how the compiler is allocating memory.
In your case, we can conclude that the variable b is stored behind the array a[4], and is incremented once after you store the fifth element into what you think is the array. The place where this happens is the b++ statement of the for loop.
I couldn't reproduce this behaviour because my compiler probably doesn't allocate b immediately behind a[4].
You made the array of the size 4 but you are entering 5 values in it.
So you could just increase the array size or make the loop enter 4 values by exchanging <= with < sign.
Hope it helps.
You are entering five numbers, not four. Change int a[4] to int a[5]. Then optionally change all your conditions to <5 for clarity, as this is usually what C programmers expect.
My problem is prettty simple, I wanna allocate memory for a 2d array in c, fill it with -1, then free it and exit the program. My code keeps crashing and I dont know what I am doing wrong...
This is what I got:
int main(){
int i,j;
char str1[]="xxxabxcxxxaabbcc";
char str2[]="abc";
int len1=strlen(str1);
int len2=strlen(str2);
printf("%d %d",len1,len2);
//allocate 2d_array
int **H_table = (int**)malloc((len1+1)*sizeof(int));
for (i=0; i<len1+1; i++){
H_table[i] = (int*)malloc((len2+1)*sizeof(int));
}
//fill and print 2d array
for(i=0;i<len1+1;i++){
for(j=0;j<len2+1;j++){
printf("i:%d j:%d",i,j);
H_table[i][j]=-1;
printf(" value:%d\n",H_table[i][j]);
}
}
// free 2d array
for(i=0;i<len1;i++){
free(H_table[i]);
}
free(H_table);
return 0;
}
So what happens is that I wanna allocate an array that has 1 extra line and 1 extra column than the 2 strings if you put them vertically compared to each other.
And this is what I expected( the things in bracets are obviously not part of the table, I put the there for comparison):
(x x x a b x c x x x a a b b c c)
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
a)1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
b)1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
c)1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
The problem is that the code crashes when it fills the table, and it always crashes for i=9 and j=3, for those specific strings. The weird part is that if you swap the 2 strings(put "abc" in str1) then the code passes the filling stage, and crashes when it tries to free the array.
Sorry for any grammar mistakes or stackoverflow mistakes, I am kinda new here :P
Any idea is welcome :) thx in advance
As a number of people have pointed out, you're allocating H_table with room for len1 + 1 integers but it is actually supposed to be an array of len1 + 1 pointers (to integers). Since pointers are bigger than integers (on your system, anyway), you end up with undefined behaviour from a buffer overrun.
Here's a hint. Avoid this problem, and a variety of other similar issues, by always using the following model for malloc:
some_variable = malloc(n * sizeof *some_variable);
For example:
int** H_table = malloc((len1 + 1) * sizeof *H_table);
for (int i = 0; i <= len1; ++i)
H_table[i] = malloc((len2 + 1) * sizeof *H_table[i]);
That is, let the compiler figure out the right type for the variable (or lvalue). The compiler is less prone to typos than you are, and not writing the type explicitly will make it a lot easier for you to later decide that H_table should have been long or short or unsigned.
For the same reason, don't explicitly cast the return value of malloc. C automatically casts void* to the destination type, and does not provide an error if you manually cast to the wrong type. So just let the compiler do it; it's less typing, safer, and more future-proof.
Note that if you use an expression with sizeof, the compiler does not evaluate the expression [Note 1]. It just figures out the type and substitutes that for the expression. So don't worry about extra evaluation: there isn't any. That's also why it's ok to use this model with declarations, even though some_variable doesn't yet have a value when the malloc is executed.
Notes:
There is one circumstance in which the compiler might evaluate ex in sizeof ex: if ex is a variable-length array. However, in this case ex is always a pointer, so that case cannot apply.
As #xing mentioned in his comment, H_table is a pointer to pointer to integer. so you need to change the int to int* in the first malloc.
here:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
int i,j;
char str1[]="xxxabxcxxxaabbcc";
char str2[]="abc";
int len1=strlen(str1);
int len2=strlen(str2);
printf("%d %d",len1,len2);
//allocate 2d_array
int **H_table = (int**)malloc((len1+1)*sizeof(int*));
for (i=0; i<len1+1; i++){
H_table[i] = (int*)malloc((len2+1)*sizeof(int));
}
//fill and print 2d array
for(i=0;i<len1+1;i++){
for(j=0;j<len2+1;j++){
printf("i:%d j:%d",i,j);
H_table[i][j]=-1;
printf(" value:%d\n",H_table[i][j]);
}
}
// free 2d array
for(i=0;i<len1;i++){
free(H_table[i]);
}
free(H_table);
return 0;
}
Problem : Although I declared two char strings , whose contents are the same , Outputs are different.
#include <stdio.h>
int main(void)
{
/* Initialization of two different array that We deal with */
char arr1[10]={'0','1','2','3','4','5','6','7','8','9'};
char arr2[10]="0123456789";
/* Initialization End */
for(int i = 0 ; i < 11 ; ++i)
{
printf("arr1[%d] is %c \t\t",i,arr1[i]);
printf("arr2[%d] is %c\n",i,arr2[i]);
if(arr1[i]=='\0')
printf("%d . character is \\0 of arr1 \n",i);
if(arr2[i]=='\0')
printf("%d . character is \\0 of arr2 \n",i);
}
return 0;
}
Expectation : I expected that both if statements are going to be true for any kind of value of 'i'.
Output : It is an output that I got it.
arr1[0] is 0 arr2[0] is 0
arr1[1] is 1 arr2[1] is 1
arr1[2] is 2 arr2[2] is 2
arr1[3] is 3 arr2[3] is 3
arr1[4] is 4 arr2[4] is 4
arr1[5] is 5 arr2[5] is 5
arr1[6] is 6 arr2[6] is 6
arr1[7] is 7 arr2[7] is 7
arr1[8] is 8 arr2[8] is 8
arr1[9] is 9 arr2[9] is 9
arr1[10] is 0 arr2[10] is
10 . character is \0 of arr2
Both cases invoke undefined behavior by accessing the array out of bounds. You cannot access index 10 of an array with items allocated from index 0 to 9. Therefore you need to change the loop to i<10 or anything might happen. It just happened to be different values printed - because you have no guarantees of what will be printed for the byte at index 10.
In both examples, there is no null terminator, so they are equivalent. Due to a subtle, weird rule in the C language (C17 6.7.9/14 emphasis mine):
An array of character type may be initialized by a character string literal or UTF−8 string
literal, optionally enclosed in braces. Successive bytes of the string literal (including the
terminating null character if there is room or if the array is of unknown size) initialize the
elements of the array.
Normally when trying to store too many initializes inside an array, we get a compiler error. But not in this very specific case with a string literal initializer, which is a "language bug" of sorts. Change to char arr2[9]="0123456789"; and it won't compile. Change to char arr2[11]="0123456789"; and it will work just fine, even when iterating over 11 elements.
There are a few small things wrong with your code and the assumptions you seem to make about it.
1. These two declarations are not the same
char arr1[10]={'0','1','2','3','4','5','6','7','8','9'};
char arr2[10]="0123456789";
The second line is equal to this:
char arr2[10]={'0','1','2','3','4','5','6','7','8','9', 0x00};
... which defines an array containing 11 elements. Check out implicit zero-termination for string literals.
EDIT:
I'm getting quite a lot of down-votes for this point specifically. Please see Lundin's comment below, which clarifies the issue.
2. Your for-loop iterates over 11 elements
for(i=0 ; i<11 ;++i)
The loop above goes through i = 0..10, which is 11 elements.... but you only wanted to compare the first 10 right?
You could change your loop to only compare the first ten elements [for(i = 0; i < 10; ++i)] and that would make your program work as you expect.
Because of what it seems you are assuming, I would recommend reading up on strings in C, array-indices and undefined behavior.
when a character array is initialized with a double quoted string and array size is not specified, compiler automatically allocates one extra space for string terminator ‘\0’
Ref
Output of the program:
#include <stdio.h>
int main()
{
int size;
printf("Enter the size of array: ");
scanf("%d",&size);
int b[size],i = 0;
printf("Enter %d integers to be printed: ",size);
while(i++ < size)
{
scanf("%d",&b[i]);
printf("%d %d\n", i, b[i]);
}
return 0;
}
for size = 5 and input numbers :
0 1 2 3 4
is
1 0
2 1
3 2
4 3
5 4
where first column is for i and second for elements of array b.
It is clear that i in the loop while(i++ < size) { incremented to 1 before entering the loop. This loop should have to store/print the value at/of b[1], b[2], b[3], b[4] but not b[5] as loop will terminate at i = 5.
How this code is printing the value of b[5]?
I have tested it for different array size and it is not printing any garbage value.
By reading and writing past the array, your program invokes undefined behavior. It doesn't mean that it has to crash or print garbage values, it can pretend working fine. Apparently, that's what is happening in this case.
In your loop, the condition i < size is checked before i is incremented. But, i is incremented before entering the body of the loop and not after it, so it is possible to access b[5] in this case, as i would be incremented after checking i < size with i=4. You do not want that, as this causes undefined program behavior.
If you try to access an element in the array which does not exist, e.g. array[size], you are accessing the next spot in the memory right after the array. In this case you are lucky, but if this meant you were accessing a part of the memory where your program isn't allowed to do so, you'd get a segmentation fault.
you could use a for cycle instead of a while so instead of while(i++<size)you could use for(i = 0; i < size; i++) that should solve your problem my friend :)
I'm creating a table of an arrays where the user can input the value themselves, and I will show them the table of value except the number 0 is use to exit from the scanf
so I don't want number 0 to be store in the array
but I'm seeing number 0 for the next value of an array so I'm wondering if 0 is a default value of an array.
to make it a bit more clear
let say the user entered;
5
4
3
2
1
and 0
so what I suppose to show in my program output is
5
4
3
2
1
which I use array to display the index of 0-4 [1-5]
but just to make sure if number 0 is not store so I call array[5] to see if the next value is 0 or something else and it always display 0 so I want to know if there is a way to make sure that 0 is not going to store in the array
this is what I use to make sure
if(enter != 0){
array[i - 1] = enter;
Sorry if my question is complicated.
Thanks
If the array is with static storage duration it will be initialized to 0. In any other case, elements will not be initialized, i.e. will contain random bits.
Static storage duration have global variables, file scope static variables and block scope static variables.
I revide my answer. Every array that you allocate can contain garbage, or not. The compiler can clear it for you, or not. In your case, I would clear the array with something like -1. Else you will have some undefined values in there, that be 0 or not. It's just not defined, every compiler can behave differently.
Test it:
#include <stdio.h>
void array(void);
int main(void) {
int c[10], i;
printf("Array 1: ");
for(i = 0; i < 10; i++) {
printf("%d", c[i]);
}
printf("\n");
array();
int b[10];
for(i = 0; i < 10; i++) {
printf("%d ",b[i]);
}
printf("\n");
return 0;
}
void array(void) {
int a[10] = {1,2,3,4,5,6,7,8,9,0};
return;
}
It depends, but generally arrays defined at compile-time are full of 0 by default. Arrays defined at run-time not necessarily, they could be 0 or full of crap.