error in printing contents of array in C - c

After i assign values to my array, and try to print its content using the for loop. The first few values of output are not the values assigned to the array.
input:-r 45 23 32 43 53 ed // these are the contents assigned to array
output:- ▒▒ 45 23 32 43 53 ed // i get that weird thing as my first value.
As the size of the array grows the more values that show up like that(▒▒).
How can i fix this so the output is as same as the input?
code used to print is as follows:
char **values = malloc(argc*sizeof(char));
for(c=1;c<=argc;c++){
printf("test value:%s\n",values[c]); // values contains the value
}

Arrays in C are zero-based.
Run your index from 0 to < argc:
for(c = 0; c < argc; ++c){
Don't use <= argc - 1 as this will give you trouble if argc is an unsigned type.
Also, don't read back the values in an array until you've assigned values to them. The behaviour on doing that is undefined in C.

Related

Why my program prints the wrong character?

Hey I am trying to understand pointers and I create a program in which I give words from keywords and I
store them in an array and after that I want to print the first character of the first word (I expected) but it prints the first character of the second word
What is going wrong?
#include<stdio.h>
#include<stdlib.h>
int main ()
{
int i=0;
char array[5][10];
for(i = 0 ; i < 5 ; i++)
{
gets(array[i]);
}
printf("\n");
char *p;
p=&array[0][10];
printf("%c",*p);
return 0;
}
The position in the array you are looking for doesn't exist, so the program is showing a random value.
The arrays go from 0 to (n-1), 'n' being 5 or 10 in your case. If you search a differente position in the range of the array you will find the correct answer.
Try changing this part of the code ('a' have to be a value from 0 to 4 and 'b' have to be a value from 0 to 9)
p=&array[a][b];
pointer are address in memory
1rst word adresses are from 0 to 9
2nd word from 10 to 19
p=&array[0][10]; points to the 10th elt so the first letter of the second word! and not for a random value as previous post suggests.
That said NEVER use gets
Why is the gets function so dangerous that it should not be used?

Odd and even number using switch case

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.

Confusing output of two different Char Array

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

How to generate all the distinct numbers which can be formed by eliminating one or more digits from left and/or right end of each number

I need to read some numbers from a file and generate all the numbers which can be formed by removing 1 digit from the start and one from the end ( for each one of my numbers read ) and print them into a new file.I know how to read and print in files so my question is more about the way I should think when solving this problem.
Here is an example for this problem:
for 3457 the output should be:
457
345
34
45
57
3
4
5
7
my initial thought was to read the numbers as an array of strings using a double pointer ( assuming I know how many numbers I should read so I can dynamically allocate memory to it ) and then to work on them.
After that I though of a way to generate the numbers that are obtained by removing 1 digit from the start and one from that end ( but not simultaneously ) for that I used a for loop:
for ( i = 1, j = (strlen(p[0]) - 2); i < strlen(p[0]) - 2, j >=0; ++i, --j ) //p[0] is my first number read from the file
{
printf("\n%s", p[0] + i); //this will print the numbers 457, 57, 7
char temp[10];
strncpy(temp, p[0], j);//I copy into a new temporary string to print the numbers 345, 34, 3
temp[j] = '\0';
printf("%s", temp);
printf("\n%s", temp + i);//this will print the numbers 45,4
}
But I have no idea on how to proceed with the rest of the numbers and i simply wasn't able to find or to think of an algorithm which will print them in that order, so I would really appreciate some help on how to solve this problem
Assuming that you have the number converted to a string (e.g. using sprintf) you could do something like this:
Take the original string and remove 0 chars from the right
Remove 0 chars from the left and print
Remove 1 chars from the left and print
Remove 2 chars from the left and print
...
Remove string length - 1 chars from the left and print
Take the original string and remove 1 chars from the right
Remove 0 chars from the left and print
Remove 1 chars from the left and print
Remove 2 chars from the left and print
...
Remove string length - 1 chars from the left and print
Take the original string and remove 2 chars from the right
Remove 0 chars from the left and print
Remove 1 chars from the left and print
Remove 2 chars from the left and print
...
Remove string length - 1 chars from the left and print
The above is easy to implement using two nested for-loops. Like:
int main()
{
char str[] = "123456";
size_t len = strlen(str);
size_t i, j;
for (i = 0; i < len; i++) // i is number of chars to remove (aka not print) from right
{
for (j = 0; j < len-i; j++) // j is number of chars to remove (aka not print) from left
{
size_t z=j;
int p = 0;
while (z < (len - i))
{
printf("%c", str[z]);
z++;
p = 1;
}
if (p) printf("\n");
}
}
return 0;
}
Output:
123456
23456
3456
456
56
6
12345
2345
345
45
5
1234
234
34
4
123
23
3
12
2
1
Now if the input string is "1001" the output of the program is (comments added manually):
1001 // ok
001 // Is this valid? Or should it be 1
01 // Is this valid? Or should it be 1
1 // ok
100 // ok
00 // Is this valid? Or should it be 0
0 // ok
10 // ok
0 // ok but repeated! Is this valid?
1 // ok but repeated! Is this valid?
As you can see there may be a problem with the algorithm, e.g. leading zero and repeated numbers. If that is invalid, you'll have to
keep track of already printed numbers
avoid printing leading zeros
The following assumes that the numbers are read from the input file as strings (null-terminated character arrays) and that those strings are valid representation of base 10 integers, not necessarily in the range of an int, just only digits.
Skip the leading zeroes. I assume that a string like "0042", if not rejected, should be interpreted as the number 42, so that the output should be only 4 and 2, without any 0. strspn could be used here.
Find the length (len) of the remaining string, if it's less then two characters, return.
Loop from 1 (included) to len (excluded). That is the number of characters to be removed from the source, let's call it i.
The size of the substrings is sub_length = len - i.
Loop from 0 to i (both included) to consider all the substrings of size sub_length. E.g. from 123 we consider first 12 and 23.
If the first character of the substring is '0' and its length is greater than 1, skip the following steps, so that e.g. from 1007 we won't print 007 nor 07, only 0 and 7.
Check if the actual substring can be found in the left part of the source string that we have already considered. E.g. given 4545, after having printed 45 and 54 we would find the last 45 in 454 and skip it. A loop with functions like strncmp or memcmp may come in handy, here, more than strstr which requires null-terminated strings as parameters.
If the previous step doesn't find a duplicate, print the substring (with a loop, or using printf with the format specifier "%.*s" as explained here).
This algorithm would produce the following results:
Source: "3457"
345 457 34 45 57 3 4 5 7
Source: "1045"
104 10 45 1 0 4 5
Source: "5454"
545 454 54 45 5 4
Source: "10000"
1000 100 10 1 0
Source: "0042"
4 2

*the counter* to reverse an array using pointers doesn't work

#include<stdio.h>
int main() {
int i;
int vector[5]={6,17,28,39,410},*r; //variables declaration
r=(int*)&vector; //pointer declaration
for (i = 0; i<5;i++){ //print the array in using a loop
printf("%d ",vector[i]);
}
printf("\n\n");
for(i=0;i<5;i++){ //print the array in reverse order using a loop
vector[i] = *(r+4-i); //it should be from the last to the first but it prints it
printf("%d ",vector[i]); //differently, see below
}
return 0;}
It should be:
6 17 28 39 410
410 39 28 17 6
but it results in:
6 17 28 39 410
410 39 28 39 410
the last two should be 17 6
You are overwriting the data you're trying to read, before reading it.
Just write out the steps your code is taking manually, and you'll see it.
To do reversal in-place, you must swap values around, to avoid overwriting.
Also note that the name of an array evaluates to a pointer to the first argument, in the proper context. So this:
r=(int*)&vector;
is much better written as just:
r = vector;
You should really avoid casts, and your cast is completely unnecessary.
try this:
#include<stdio.h>
int main() {
int i;
int vector[5]={6,17,28,39,410},*r; //variables declaration
r=(int*)&vector; //pointer declaration
for (i = 0; i<5;i++){ //print the array in using a loop
printf("%d ",vector[i]);
}
printf("\n\n");
for(i=0;i<5;i++){ //print the array in reverse order using a loop
//it should be from the last to the first but it prints it
printf("%d ",*(r+4-i)); //differently, see below
}
return ( 0 );
}
In your code you are changing the first two values. So first two steps Your array
will be like this.
410 39 28 39 410
After that loop continues it will get that replaced value. You can store the replaced value in the another array.
for(i=0,j=4;i<j;i++,j--){
temp=vector[i]; // storing the value in temporary variable
vector[i] = r[j];
r[j]=temp; // assigning the value .
}
for ( i=0; i < 5 ; i ++ )
printf("%d\n",vector[i]);

Resources