Corrupted 2D Char Array After Cycle - c

i'm writing a simple C program where i'm getting the names of the places(lugares) that have been raining, this is just a practice exercise, the thing is that somehow after the cycle where i get the amounts of pluviosity(pluviosidad) the 2d char array of places(lugares) gets corrupted and its first element loses its content and ends up with garbage, I've been thinking of why this happens in the last 4 hours trying to fix this and I don't see why it happens. Any help would be highly appreciated, thanks in advance!
PD: As far as i'm aware of a 2D Char array works like this [sizeofthearray][lengthofeachelement] so I don't know if somehow i'm making this array unstable, since i'm just using the %-10s to format the outputs. And the lengths of its contents aren't even beyond to 12-15 characters i placed 25 just in case i need more when it gets evaluated.
const int nDias = 5;
const int nLugares = 3;
int i, j;
// Arrays Creation
char lugares[nLugares][25];
float pluviosidad[nLugares][nDias];
// A) Data loading
for (i = 0; i<nLugares; i++){
printf("Ingrese el Nombre del Lugar %d:\n", i + 1);
gets_s(lugares[i]);
fflush(stdin);
}
// Somehow after these 2 cycles finish, the "lugares" 2d char array gets corrupted. (I noticed this when doing a debugging session in visual studio)
for (i = 0; i<nLugares; i++){
system("cls");
for (j = 0; j<nDias; j++){
printf("Ingrese pluviosidad para %s en el dia %d: ", lugares[i], j + 1);
scanf_s("%f", &pluviosidad[j][i]);
}
}
// Output Data
printf("\t\tLugares\n");
printf("%-10s", "Dias");
// and here I try to see its contents and in this case of 3 elements on the lugares 2d char array, the first element loses its contents and ends up with garbage.
for (i = 0; i<nLugares; i++)
printf("%-26s", lugares[i]);

Related

C - Passing a 3D arrays of chars to a function

I'm trying to write a program that analyzes a (3 x 4) matrix of strings provided by the user. Ultimately, it needs to output the longest string present in the matrix, along with that string's length.
My program seems to read the input correctly, as judged its success in echoing back the input strings, but it does not correctly output the longest word. I'm sure I'm committing some kind of pointer-related error when I pass the value of longest word, but I do not have any idea how to solve it.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define M 4
#define N 5
#define MAX_DIM 20
void findMAX(char matrice[N][M][MAX_DIM]) {
char maxr;
int index;
int i, j, it;
index = 0;
maxr = *(*(*(matrice+0)+0)+MAX_DIM);
for (i = 0; i < N-1; i++) {
for (j = 0; j < M-1; j++) {
if (index < strlen(matrice[i][j])) {
index = strlen(matrice[i][j]);
// I save the longer line's value
it = i;
// I save the maximum's value
maxr = *(*(*(matrice+i)+j)+MAX_DIM);
}
}
}
printf ("The MAX is: -/%s/- and it's long: -/%d/- \n", maxr, index);
printf ("It is content in the: %d line, which is: \n", it);
for (j = 0; j < N-1; j++) {
printf("%s ", matrice[it][j]);
}
}
void leggi(char matrice[N][M][MAX_DIM]) {
int i, j;
for (i = 0; i < N-1; i++) {
for (j = 0; j < M-1; j++) {
printf ("Insert the element matrix [%d][%d]: ", i, j);
scanf ("%s", matrice[i][j]);
fflush(stdin);
}
}
}
void stampa(char matrice[N][M][MAX_DIM]) {
int i, j;
printf("\n(4 x 3) MATRIX\n");
for (i = 0; i < N-1; i++) {
for (j = 0; j < M-1; j++) {
printf("%s ", matrice[i][j]);
}
printf("\n\n");
}
}
int main(int argc, char *argv[]) {
char matrix[N][M][MAX_DIM]; //Matrix of N*M strings, which are long MAX_DIM
printf("************************************************\n");
printf("** FIND THE LINE WITH THE MAXIMUM ELEMENT **\n");
printf("** IN A (4 x 3) MATRIX **\n");
printf("************************************************\n");
printf ("Matrix Reading & Printing\n");
leggi (matrix);
stampa (matrix);
findMAX(matrix);
return 0;
}
First of all to address some misconceptions conveyed by another answer, consider your 3D array declared as
char matrix[N][M][MAX_DIM];
, where N, M, and MAX_DIM are macros expanding to integer constants.
This is an ordinary array (not a variable-length array).
If you want to pass this array to a function, it is perfectly acceptable to declare the corresponding function parameter exactly the same way as you've declared the array, as indeed you do:
void findMAX(char matrice[N][M][MAX_DIM])
But it is true that what is actually passed is not the array itself, but a pointer to its first element (by which all other elements can also be accessed. In C, multidimensional arrays are arrays of arrays, so the first element of a three-dimensional array is a two-dimensional array. In any case, that function declaration is equivalent to both of these:
void findMAX(char (*matrice)[M][MAX_DIM])
void findMAX(char matrice[][M][MAX_DIM])
Note in particular that the first dimension is not conveyed. Of those three equivalent forms, I find the last clearest in most cases.
It is quite odd, though, the way you access array elements in your findMAX() function. Here is the prototypical example of what you do:
maxr = *(*(*(matrice+i)+j)+MAX_DIM);
But what an ugly and confusing expression that is, especially compared to this guaranteed-equivalent one:
maxr = matrice[i][j][MAX_DIM];
Looking at that however, and it how you are using it, I find that although the assignment is type-correct, you are probably using the wrong type. maxr holds a single char. If you mean it to somehow capture the value of a whole string, then you need to declare it either as an array (into which you will copy strings' contents as needed), or as a pointer that you will set to point to the string of interest. The latter approach is more efficient, and I see nothing to recommend the former for your particular usage.
Thus, I think you want
char *maxr;
... and later ...
maxr = matrice[0][0];
... and ...
maxr = matrice[i][j];
That sort of usage should be familiar to you from, for example, your function stampo(); the primary difference is that now you're assigning the expression to a variable instead of passing it directly to a function.
And it turns out that changing maxr's type that way will correct the real problem here, which #AnttiHaapala already pointed out in comments: this function call ...
printf ("The MAX is: -/%s/- and it's long: -/%d/- \n", maxr, index);
requires the second argument (maxr) to be a pointer to a null-terminated array of char in order to correspond to the %s directive in the format string. Before, you were passing a single char instead, but with this correction you should get mostly the expected result.
You will probably, however, see at least one additional anomaly. You final loop in that function has the wrong bound. You are iterating with j, which is used as an index for the second dimension of your array. That dimension's extent is M, but the loop runs to N - 1.
Finally, I should observe that it's odd that you allocate space for a 5 x 4 array (of char arrays) and then ignore the last row and column. But that's merely wasteful, not wrong.
Try something like this:
void findMAX(char matrice[N][M][MAX_DIM]){
// char maxr
char maxr[MAX_DIM];
int index;
int i, j, it;
index = 0;
// maxr = *(*(*(matrice+0)+0)+MAX_DIM);
strncpy(maxr, *(*(matrice+0)+0), MAX_DIM);
for (i = 0; i < N-1; i++)
{
for (j = 0; j < M-1; j++)
{
if (index < strlen(matrice[i][j]))
{
index = strlen(matrice[i][j]);
it = i;
// maxr = *(*(*(matrice+i)+j)+MAX_DIM);
strncpy(maxr, *(*(matrice+i)+j), MAX_DIM);
}
}
}
printf ("The MAX is: -/%s/- and it's long: -/%d/- \n", maxr, index);
printf ("It is content in the: %d line, which is: \n", it);
// for (j = 0; j < N-1; j++){
for (j = 0; j < M-1; j++){
printf("%s ", matrice[it][j]);
}
}
It's possible to pass multi-dimensional arrays to C functions if the size of the minor dimensions is known at compile time. However the syntax is unacceptable
void foo( int (*array2d)[6] )
Often array dimensions aren't known at compile time and it is necessary to create a flat array and access via
array2D[y*width+x]
Generally it's easier just to use this method even if array dimensions are known.
To clarify in response to a comment, C99 allows passing of variable size arrays using the more intuitive syntax. However the standard isn't supported by Microsoft's Visual C++ compiler, which means that you can't use it for many practical purposes.

fscanf crashing my C program, no idea why

EDIT: Question answered, I had a typo in my first for loop. Thanks so much everyone for catching that.
I'm working a C project for uni, and I'm having a problem I just cannot figure out. In one section of the program, I have to read in a few strings of symbols into a 2D character array in a struct (aka a "stamp"). Here is the code in my function:
stamp_t * read_stamp_type1(FILE * fptr)
{
//variable declaration
int r = 0, c = 0;
//creating a struct stamp_t and mallocing memory
stamp_t *newstamp1;
newstamp1 = malloc(sizeof(stamp_t));
//reading in values for the rows and columns of the "stamp" to be read in
fscanf(fptr, "%d %d\n", &r, &c);
//storing these values
newstamp1->num_rows = r;
newstamp1->num_cols = c;
//creating memory for newstamp1's grid
newstamp1->grid = malloc(sizeof(char *) * (r));
for(int i=0; i < c; i++)
newstamp1->grid[i] = malloc(sizeof(char) * (c+1));
//string to temporarily store input
char rowvalues[c+1];
//Note: Everything works up until this point
//the below lines crash the program every time
for(int i = 0; i < r; i++)
{
fscanf(fptr, "%s", rowvalues);
for (int j=0; j < c; j++)
strcpy(newstamp1->grid[i], rowvalues);
}
free(rowvalues);
return(newstamp1);
}
For some reason when I try to fscanf the string from the text file, it crashes the program (or at least that's what I think the cause is...).
For reference, here is the struct declaration:
// A structure for holding a stamp
typedef struct
{
// The size of the contents of this stamp.
int num_rows;
int num_cols;
// A 2D array of characters for a stamp.
char **grid;
} stamp_t;
And here is the input to the program:
3 4
.#.#
#.#.
.#.#
Any advice would be greatly appreciated, I can't seem to find any problem with the code. I have tried manually assigning values to each value in the rowvalues array, which works fine (rowvalues[0] = 'c'; works fine). I need to read in the 3 lines of symbols into newstamp1.grid, which is a 2D array. I ran a debugger and it said it's try to write to memory that is not allowed ("Access violation writing location"). I emailed my professor but he hasn't be in class for the past week and he isn't responding to email...
Thanks so much in advance.
For starters there is a typo in this loop
newstamp1->grid = malloc(sizeof(char *) * (r));
for(int i=0; i < c; i++)
^^^^^^
newstamp1->grid[i] = malloc(sizeof(char) * (c+1));
There must be
for(int i=0; i < r; i++)
^^^^^^
This loop
for (int j=0; j < c; j++)
strcpy(newstamp1->grid[i], rowvalues);
does not make sense. It seems you mean just
strcpy(newstamp1->grid[i], rowvalues);
Or maybe you have to allocate a 3D character array (that is a two dimensional array of strings) if each row in the file contains c strings.
And this statement
free(rowvalues);
is wrong. The variable rowvalues has automatic storage duration. So you may not call the function free for it.
This part of your code is nonsense:
newstamp1->grid = malloc(sizeof(char *) * (r));
for(int i=0; i < c; i++)
newstamp1->grid[i] = malloc(sizeof(char) * (c+1));
You allocate r items, and then your for is repeated as c-times. This should be the same, either both r, or both c. I bet i < r is correct condition there.
Also, as Vlad from Moscow pointed out, there is one more bug in the code: The final free shouldn't be there at all, because it wasn't mallocated. And the for-j line can also be omitted. (But it shouldn't produce any errors, it just unneededly repeats the same code.)

Is this implementation of insertion in array incorrect?

I was reading a tutorial at tutorialspoint.com for Data Structures.
In the section about the array data structure is this implementation of insertion an element in an array, which is accesing an element outside of the bound of the array :
int LA[] = {1,3,5,7,8};
int item = 10, k = 3, n = 5;
int i = 0, j = n;
printf("The original array elements are :\n");
for(i = 0; i<n; i++) {
printf("LA[%d] = %d \n", i, LA[i]);
}
n = n + 1;
while( j >= k){
LA[j+1] = LA[j];
j = j - 1;
}
LA[k] = item;
printf("The array elements after insertion :\n");
for(i = 0; i<n; i++) {
printf("LA[%d] = %d \n", i, LA[i]);
}
Is'nt accesing an element outside of the bounds of an array undefined behaviour and therefore very bad practice?
If so why is this given in a tutorial?
Is'nt accesing an element outside of the bounds of an array undefined behaviour
Yes. Good spotting.
and therefore very bad practice?
I can't argue with that, except maybe to say that it's a little understated. A program that exhibits UB is flat wrong.
If so why is this given in a tutorial?
I can only speculate, but that section of the tutorial is not only wrong, but altogether poorly conceived. C arrays have fixed length, therefore you cannot "insert" into a C array in any sense that preserves all the values that already were there. (I disregard dynamic memory approaches, which are not relevant to the code presented.)
You can use code similar to that presented in the example if you adjust it to avoid reading or writing past the end of the array. Such an approach to "inserting" an element must lose the element originally at the array's end.
Of course it's a bad practice. When you try to do
while( j >= k){
LA[j+1] = LA[j];
j = j - 1;
}
... you will have LA[6] receiving a value when LA has size 5. Then an error message will be shown and at some moment the execution will be aborted. Besides that the exit status (echo $?) will be different of zero, i.e., it is saying that your program wasn't finished with successful.

Array doesn't print in reverse in C using pointers

I am trying to make a program that takes 10 numbers as input and outputs them in reverse order using pointers in C.
#include<stdio.h>
#define N 10
int array[N]; //Global variable
int main(void) {
int j;
int i;
printf("Enter 10 numbers: ");
for (i=0;i<N;i++) {
scanf("%d",(array+(4*i))); //Works
}
for (j=N-1;j<0;j--) {
printf("%d",array[j]); //Doesn't print, using *(array+j*4) doesn't
//print also
}
printf("\n");
printf("%d\n",*(array)); //Works so scanf works
printf("%d\n",*(array+4)); //Works so scanf works
return 0;
}
I have tried a making a seperate function for the two for loops but still it doesn't work. I want to know WHY this for-loop doesn't print but the two printfs below it print.
EDIT:
My new code is
#include<stdio.h>
#define N 10
int array[N]; //Global variable
int main(void) {
int j;
int i;
printf("Enter 10 numbers: ");
for (i=0;i<N;i++) {
scanf("%d",(array+i)); //Works
}
for (j=N-1;j<0;j--) { //it is supposed to be j>=0 or j>0 WHY
printf("%d",array[j]); //Doesn't print, using *(array+j) doesn't
//print also
}
printf("\n");
printf("%d\n",*(array)); //Works so scanf works
printf("%d\n",*(array+1)); //Works so scanf works
return 0;
}
Thanks to all the posts, I have a better understanding of how indexing works in C now but the printf doesn't work still unless I change the for-loop conditions(see above). WHY doesn't it work with the initial conditions but with the latter conditions.
Whoa!
This:
scanf("%d",(array+(4*i))); //Works
is very wrong and is overwriting memory! Why are you multiplying the index? You don't need to do that, C can index by itself. It should just be:
scanf("%d", &array[i]);
You want the address of the i:th array member, so say that, don't beat around the bush with strange multiplications.
If you really want to be "using pointers", as mentioned in a comment, you can do so:
scanf("%d", array + i);
This works since array is a pointer to the first element of the array, and adding i to is a fully valid use of pointer arithmetic; C will compute the proper pointer, knowing the size of each int in the array.
Your array consists of 10 elements with type int (obviously). In expression array + i variable i is not an offset in bytes. It is an index of element. So when you read it like you do (scanf("%d",(array+(4*i)))) you basicly read array[0], array[4], array[8], array[12] (we're out of array bounds here already, it causes memory corruption and might cause crashes), etc. Elements array[1],[2],[3],[5], etc. are uninitialized. That's why your code doesn't work :)
UPDATE:
And #shilong-liu's note about array indices is important, too. I didn't notice it.
for (j=N-1;j<0;j--) {
printf("%d",array[j]); //Doesn't print, using *(array+j*4)
}
the for loop is not right. The correct one is that
for (j = N - 1; j > 0; j--)
I guess since the pointer used is of type int, you assume that you have to multiply i by 4 because depending on the compiler int is 4 bytes. I guess if you really care only about the output, then you could do it the way you did with reverse iteration.
What you have to do has been already mentioned by the others so I will give you my solution for actually swapping the pointers memory wise and you could choose from the given solutions:
#include<stdio.h>
#define N 10
int array[N]; //Global variable
int main(void) {
int j;
int i;
printf("Enter 10 numbers: ");
for (i=0; i<N; i++) {
scanf("%d", (array + i));
}
for (left = 0; left < N / 2; left++)
{
int right = N - left - 1;
int temporary = array[left];
array[left] = array[right];
array[right] = temporary;
}
for (i=0; i<N; i++) {
printf("%d", (array + i));
}
return 0;
}
I have been programming for algorithmic contests so you could trust me.

Why do some C programs work in debug but not in release?

Ok,
So I am stuck here. I have code for a program that systematically executes people standing in a circle based off an algorithm, but I am having a problem with it crashing in release mode. My code runs fine if I run it using the debugger (codeblocks), but if I don't it crashes. I looked around online, and the only thing I am finding is unintialized variables, but I tried immediately setting values for my variables at declaration and it didn't fix the problem.
If anyone can see what my problem is, I would greatly appreciate help.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
// if the program does not work, please run in debugger mode. It will work.
void remove_person(int** array, int arraySize, int position)
{
int i;
for (i = 0; i < arraySize; ++i)
printf("%d ", (*array)[i]);
printf("\n");
int* temp = malloc((arraySize - 1) * sizeof(int)); // create temporary array smaller by one element
memmove(temp,*array,(position+1)*sizeof(int)); // copy entire array before position
memmove(temp+position,(*array)+(position+1),(arraySize - position)*sizeof(int)); // copy entire array after postion
for (i = 0; i < arraySize - 1; ++i)
printf("%d ", (temp)[i]);
printf("\n");
free (*array);
*array = temp;
}
int kill(int** a, int n)
{
int pos = 0;
int round = 1;
while(n > 1)
{
pos = pos + 2 - (round % 2);
while(pos >= n)
pos = pos - n;
remove_person(a,n,pos);
n--;
while(pos >= n)
pos = pos - n;
round++;
}
return *a[0];
}
void main()
{
int n, survivor, i;
int* people;
printf("Enter number of people for Russian Roulette: \n");
scanf("%d", &n);
people = (int*) malloc(n*sizeof(int));
for(i=0; i < n; i++)
{
people[i] = i;
}
survivor = kill(&people, n);
printf("The survivor is person #%d\n", survivor);
}
The basic answer to the title question ("Why do some C programs work in debug but not in release?") is "when they invoke undefined behaviour".
Here, in
memmove(temp,*array,(position+1)*sizeof(int)); // copy entire array before position
memmove(temp+position,(*array)+(position+1),(arraySize - position)*sizeof(int)); // copy entire array after postion
you copy too much. To see why, observe that the first memmove copies to temp[0], temp[1], ..., temp[position], and the second copies to temp[position], temp[position+1], ..., temp[position+arraySize-position-1] = temp[arraySize-1] (note the overlap at temp[position]). But temp only has space for arraySize-1 elements -- you copied one more than it was allowed to hold, so you get undefined behaviour.
It probably works in debug but not release mode because the heap is laid out differently (debug-mode allocators may pad the allocations with extra space to catch bugs like this when running under a debugger or profiler).
The program segfaults if I enter 4 (or even numbers higher than 4) as input, but I won't go into the code to see why that happens.
Apart from that the program works just fine, the problem is that you don't see the output because I think you run it on windows.
That being said you should add something like scanf("%d", &n); at the end or run cmd.exe, go to the directory that holds the executable and run it from there.

Resources