2 dimensional array in C language - c

I am passing a 2d array to a function to print the output, but the output I am getting is erroneous
function
void PrintArray(unsigned char mat[][4]){
int i, j;
printf("\n");
for(i = 0;i<4;i++){
for(j = 0;j<4;j++)
printf("%3x",mat[i][j]);
printf("\n");
}
printf("\n");
}
main function
int main(){
int i,j;
//static int c=175;
unsigned char state[4][4], key[4][4], expandedKey[176];
printf("enter the value to be decrypted");
for(i=0;i<4;i++)
for(j=0;j<4;j++)
scanf("%x",(unsigned int *)&state[j][i]);
PrintArray(state);
return 0;
}
expected output
1 5 9 c
2 6 0 d
3 7 a e
4 8 b f
actual output
h2o#h2o-Vostro-1015:~$ ./a.out enter the value to be decrypted 1 2 3 4 5 6 7 8 9 0 a b c d e f
1 5 9 c
0 0 0 d
0 0 0 e
0 0 0 f
I checked the method of passing 2d array, its correct I think, but not sure why m getting this output, kindly advise...

I'm going to go out on a limb and say that your problem lies here:
scanf("%x",(unsigned int *)&state[j][i]);
state[i][j] is sized to hold a single char, but you're telling scanf to treat it as a pointer to unsigned int; this likely means that scanf is overwriting adjacent array elements, since sizeof (unsigned int) is most likely greater than sizeof (char).
Change the declaration of the array from char to unsigned int in both main and PrintArray, and lose the cast in scanf.

The array passing is correct. However, the scanf function seems to overwrite some values to be 0 due to the variable type %x.
The data type specified by %x is "int" because %x is like %d (except that the input is hexadecimal). The data occupies 4 bytes (typically). So when the user enters a number, say, 1, four bytes 01 00 00 00 (assuming little-endianness on an Intel machine) will be written to memory instead of 1. The trailing 0s will erase some existing elements that are stored in the byte array, because in the byte array, each element is allocated only 1 byte.
Try the following code:
int main() {
int i,j;
//static int c=175;
unsigned char state[4][4], key[4][4], expandedKey[176];
printf("enter the value to be decrypted");
int tmp;
for(i=0;i<4;i++)
for(j=0;j<4;j++) {
scanf("%x", &tmp);
state[j][i] = (char)tmp;
}
PrintArray(state);

Related

Why are these indices not getting the same thing from a 2d malloc'd C array?

Data file I am reading from:
$ cat temp.txt
0 1 2 3
4 5 6 7
8 9 10 11
C code:
#include<stdio.h>
#include<stdlib.h>
void main(){
int matsize = 12;
int numrows = 3;
int numcols = 4;
int** mat=malloc(matsize*sizeof(int*));
for(int i=0;i<numrows*numcols;++i){
mat[i]=malloc(sizeof(int));
}
FILE *file;
file=fopen("temp.txt", "r");
for(int i = 0; i < numrows; i++){
for(int j = 0; j < numcols; j++) {
if (!fscanf(file, "%d", &mat[i][j]))
break;
}
}
fclose(file);
printf("%d\n",mat[numrows-1][numcols-1]);
printf("%d\n", mat[2][3]);
printf("%d\n", mat[1][5]);
printf("%d\n", mat[0][11]);
printf("Done allocating.\n");
}
$ ./a.out
11
11
0
7
The first two outputs are both 11 as expected. For a 12 item array, I was expecting mat[1][5] and mat[0][11] to output the same thing as mat[2][3] (i.e. the 12th element, i.e. the [i+1th][j+1th] element). My understanding is that internally, the array declared here:
int** mat=malloc(matsize*sizeof(int*));
is not really a 2x3 array, rather it's just a matsize array and that accessing it via mat[i][j] just kind of divides it into [i] rows then gets the [jth] element of the ith row. Does the compiler "know" the array should be a 3x4 array because I am reading the text file in with the line if (!fscanf(file, "%d", &mat[i][j])) ? Does this scanning statement permanently change the mat object into 3 pointers of 4-length integer arrays? Or is it really just still a 12-length array, which should be accessible via dividing into two 6's, one 12, etc (if so, then why didn't the last two indexings print out the right thing)?
Follow up: If I change everything from %d/ints to %lf/doubles, I get this output with the same indexing:
11.000000
11.000000
9.000000
11.000000
Why is, for example, mat[0][11] coming out to 7 when everything is an int, but 11.000000 (as expected) when things are floats?
You should allocate a 2D array instead. It can be done as
int (*mat)[rows][cols] = malloc( sizeof(int[rows][cols]) );
However, to enable the conventient mat[i][j] syntax, you have to drop one of the dimensions in the pointer type:
int (*mat)[cols] = malloc( sizeof(int[rows][cols]) );
Not only does this get rid of the needless complexity and bugs, it also enables you to read the whole file with a single fread call, since you have a real 2D array now, instead of some fragmented pointer-to-pointer thing.
Don't forget the free(mat); at the end.

why strlen() function is giving wrong value

I don't understand why strlen() is giving wrong value (ie: 9) only for the first string. After that the values are coming correctly.
#include <stdio.h>
#include <string.h>
int main() {
int m, i, j;
i = 2;
j = 5;
char a[i][j];
for (i = 0; i <= 2; i++) {
scanf("%s", a[i]);
}
m = strlen(a[0]);
printf("%d\n", m); //here the problem is coming//
m = strlen(a[1]);
printf("%d\n", m);
m = strlen(a[2]);
printf("%d\n", m);
return 0;
}
INPUT:
heyman
jack
bro
OUTPUT:
9
4
3
Each row of a is only 5 bytes. When you read heyman into a[0], it overflows into a[1]. So you have:
a[0] = "heyma"
a[1] = "n\0"
Then when you read into a[1], you have
a[0] = "heyma"
a[1] = "jack\0"
Notice that there's no null terminator in a[0]. So when you call strlen(a[0]), it goes past the end of a[0] and continues searching in a[1] for the null byte. There are 5 bytes in a[0] and 4 bytes in a[1], so the length is 9. Technically, this is undefined behavior, but this is what happens in actual implementations because 2-dimensional arrays are contiguous.
In addition, when you read into a[2] you're completely outside the a array, resulting in undefined behavior.
Since your array has length [2][5] you can store a maximum of 2 words of length 4, every word also has the terminating character \0 in addition to its letters.
You having as input heyman means you are writing too many letters and don't have enough space to also store the \0. Either try with a shorter word or change your length from 5 to 7.
Also you are storing 3 words in your array of length 2, the length refers to the number of elements stored not to the number you can go up to. Length 2 will have available positions 0 and 1 so when you are passing as input the third word you are trying to write outside of the array bounds.

Dynamically allocating 2d array in c error

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;
}

Array becomes larger than declared [duplicate]

This question already has answers here:
How do I determine the size of my array in C?
(24 answers)
Closed 5 years ago.
I'm writing a function that is supposed to split a string on "-" and return and array containing the parts from the string, so if the string is:
2017-10-23
I want the array to have three elements populated like:
arr[0] = 2017, arr[1] = 10, arr[2] = 23
This is the function:
/*
* return a array of the parts of date_string
*/
int * to_date_array(char *date_string)
{
int i = 0;
int f = 0;
char *tokens = strtok(date_string, "-"); /* get initial token */
static int arr[3] = {0, 0, 0};
char *ptr;
int val;
/* init static arr */
for (f = 0; f < sizeof(arr); f++)
arr[f] = 0;
/* do the split */
while (tokens != NULL) {
val = strtol(tokens, &ptr, 10);
arr[i++] = val;
tokens = strtok(NULL, "-");
}
/*
* for some reason arr becomes 12 elements long?
* I expected it to have 3 elements
*/
puts("func: to_date_array");
puts("------------------------");
for (f = 0; f < sizeof(arr); f++)
printf("arr[%d]: %d\n", f, arr[f]);
return arr;
}
The function works but I'm really puzzled by the "arr" array. I expect it to be three elements long but when I iterate through it and print every element, it show 12 elements?
$ gcc -Wall main.c arguments.c -o timespan
$ ./timespan 2015-08-10 2017-10-18
func: to_date_array
------------------------
arr[0]: 2015
arr[1]: 8
arr[2]: 10
arr[3]: 0
arr[4]: 0
arr[5]: 0
arr[6]: 0
arr[7]: 0
arr[8]: 0
arr[9]: 0
arr[10]: 0
arr[11]: 0
The sizeof operand returns a size in bytes (where by definition a char takes one byte). On your (and mine) machine, sizeof(int) is 4, hence an array of 3 int takes 12 bytes. See nucleon's answer.
Your to_date_array is not reentrant. It would be nicer to return a dynamically allocated array (e.g. with calloc ....). Of course you need then to adopt the convention that its result has to be later free-d (e.g. by the caller).
You could consider also returning a pointer to some struct ending with a flexible array member.
You could also pass arr (and its length) to the to_date_array and have it been filled by that function.
sizeof computes the size of the array in bytes, thus you have to divide by the size of a single element to get the number of elements, thus use
sizeof(arr)/sizeof(*arr)
sizeof returns the number of bytes in the array, not the number of elements. On your system, an int is 4 bytes wide, so the array takes up 12 bytes.
You need to divide the size of the array by the size of a single element to get the number of elements:
sizeof arr / sizeof *arr
C does not do any bounds checking on array access - the array is only three elements wide, but you won't get any sort of OutOfBounds exception if you attempt to access elements outside of that range. The behavior is undefined - your code may crash, it may produce unexpected results, it may work as intended, but the results won't necessarily be repeatable or predictable.
sizeof int arr[3] is sizeof(int) * 3 equals to 4*3 = 12

Why is the seventh variable 6 in my program?

#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.

Resources