Printing struct shows garbage - c

I´m trying to do a simple exercise where should I should enter 2 inputs (monto and loc) in a struct using pointers and malloc. When I try yo print the data it shows garbage. I tried to check what was happening so I print the data after entering and shows things like
-1414812757 -158839287345460020000000000000000000000.00
struct transaccion{
int loc;
float monto;
char nombre[50];
} cliente,*pcliente;
int cargadatos (struct transaccion*);
void mostrarlocalidad(struct transaccion*,int);
void mostrarestructura(struct transaccion*);
void main()
{
int tam=50,ll;
struct transaccion *pTrans;
pTrans=(struct transaccion*)malloc(sizeof(struct transaccion)*tam);
pTrans[0].monto=5;
if(pTrans==NULL){
puts("Falta memoria");
exit(3);
}
ll=cargadatos(pTrans);
mostrarlocalidad(pTrans,ll);
free(pTrans);
system("pause");
}
int cargadatos (struct transaccion *pTrans)
{
int i=0;
while (pTrans[i].loc!=0){
puts ("ingrese numero de localidad");
scanf("%d", &pTrans[i].loc); fflush (stdin);
puts ("ingrese monto");
scanf("%.2f",&pTrans[i].monto); fflush(stdin);
int j=0;
for (j=0; j<=i; j++) {
if (pTrans[j].loc==pTrans[i].loc){
pTrans[j].monto=pTrans[j].monto+pTrans[i].monto;
i--;
}
}
printf("%d %.2f \n",pTrans[i].loc,pTrans[i].monto);
i++;
}
return;
}
I´ve been trying many things for hours but I cant figure it out where are the errors.

The reason you're seeing garbage is because your j loop is wrong. Since you are iterating through <= i, your check will always be true. In the first entry, you're checking pTrans[j].loc==pTrans[i].loc with both i and j being 0. Therefore you set the values of j to itself, and decrement i. When your printf runs, you're printing pTrans[-1] and not pTrans[0] as you probably are thinking you're doing.
Your easiest fix is to change your j loop to be j < i and not j <= i. That way it won't ever run against itself which seems silly anyway.

There are three problems here caused by the same mistake - a wrong condition on the j loop.
What I assume you are trying to do is read into an array element, and
scan all previous array elements and see if you already have something at that location-in which case you want to use the "old" element for the count and then reuse the new element.
Now the range on the j loop being wrong will cause 3 problems:
You will ALWAYS read into element 0.
You will ALWAYS have the monto double what it should be
You will ALWAYS print array element [-1] which is not initialized and not what you ever intended.
This happens because when i=0, your j (being <=0) will compare pTrans[0].loc==pTrans[0].loc.
As this is always true, you will now double your pTrans[0].monto (not what you expect) giving a wrong result to start with.
Now i is decremented in an attemp to reuse it - making i==-1.
You now print this, uninitialized, unexpected [-1] element giving you whatever happens to be in that memory location.
Now you get hit by a third effect - you increment i making it 0, and iterate the while with the 0 element again.
ALL this is the result of one small mistake: using the condition j<=i in the j loop.
If you change this to
for (j = 0 ; j < i ; j++)
your program will probably work ok.

struct transaccion{
int loc;
float monto;
char nombre[50];
} cliente,*pcliente;
You declared two variables that you don't use anywhere.
pTrans=(struct transaccion*)malloc(sizeof(struct transaccion)*tam);
Casting from malloc is not necessary.
the following block should be placed before you use the pointer.
if(pTrans==NULL){
puts("Falta memoria");
exit(3);
}
This loop may or may not be executed, depending on the random value you will find in the specified memory area.
while (pTrans[i].loc!=0){
What is said in the other answers remains true as well.

Thanks a lot to everyone, now I realized that I made way to much mistakes. Also I know that there variables I´m not using its because of thing I didn't implement yet. I'll correct it and post the working code.

Related

code with array subscript references and pointer dereferencing compiles and runs but the results are unexpected

Why this program can compiling and run but the result is out of my expectation?`
#include<stdio.h>
int main(void)
{
char *message="hello";
for(int i=0;*message!='\0';i++)
{
printf("%c",message[i]);
}
return 0;
}
But this one can meet my expection.(print "hello" rightly)
int main(void)
{
char *message="hello";
for(int i=0;*message!='\0';i++)
{
printf("%c",*message++);
}
return 0;
}
In the C language,arr[i] is equal to *arr.But in the cases I show above,the result is totally different,when I run them in the devc++.Due to my limited knowledge ,I can't understand this.
Because I'm a student who is going to be a freshman after this summer vacation and only have some konwledge about C language,please answer my question in a more acceptable way. Thanks in advance!
***sorry ,the problem is caused because of my carelessness.I have learned my mistake.
In the C language, arr[i] is equal to *arr....
No, *arr is equal to arr[0].
In your first example, you type message++ which make et points on the next character.
So, the first code can be corrected that way:
for(int i=0; message[i]!='\0'; i++)
{
printf("%c",message[i]);
}
And the second can be simplified: (you don't need i):
for( ;*message!='\0'; )
{
printf("%c",*message++);
}
In the first code, the pointer message isn't changed and what the pointer message points at is also not changed, so the condition *message!='\0' is always true (doing 'h'!='\0').
Therefore, i will continuously be incremented and become so large that message[i] goes out of a region where access is allowed.
The condition should be message[i]!='\0' to avoid this error.
If you want to stick to use * operator for some reason, it should be *(message+i)!='\0'.
I rewrite the program with a slightly different appearance
#include<stdio.h>
int main(void)
{
char *message="hello";
for(int i=0; 'h'!='\0';i++) // notice the change here
{
printf("%c",message[i]);
}
return 0;
}
You see the problem now?
*message is always h, it's not changing with the loop iteration. The comparison is meaningless here, it does not terminate the loop as expected.
You need to ensure that you change the pointer to the next address every time you iterate, to ensure you are checking the value of the next element.
You can make use of the index value, like
for(int i=0; * (message + i) !='\0';i++)

Enter unknown number of array values in C/C++ has strange behaviour

I need to populate an array of integers with an unknown number of elements. I am using a while loop to input values and exit the loop as a non integer value is entered. Outside the loop an integer j is initialized at 0 and used to address array elements inside the loop. At each round of the loop I check the value of j before and after the input value is assigned to array element v[j], then j is incremented.
Depending on the size chosen for the array in the declaration, (in the example below v[8]), index j is unexpectedly affected by the assignment itself: in the example below when j equals 11 before the assignment it becomes 2 after the assignment, thereafter messing it all up. As a result the code fails to assign the correct input values to the array.
I am surely lacking some deeper knowledge about C/C++ array management... anyone can help to to fill the gap explaining the apparently strange behaviour of my code?
#include <stdio.h>
int main()
{
int j = 0, m, v[8];
printf("Enter an integer: to finish enter x\n");
while (scanf("%d", &m))
{
printf("j before assignment:%d - ", j);
v[j] = m;
printf("j after assignment:%d - ", j);
printf("v[j] after assignment:%d\n", v[j]);
j++;
}
return 0;
}
You write beyond the array boundaries of v. To avoid this, check j in a for loop, e.g. replace while (...) with
for (j = 0; j < 8 && scanf("%d", &m) == 1; ++j) {
// ...
}
This way, the loop stops after the end of the array (v[7]) is reached.
To comment the "strange" behaviour, read about stack and stack layout, e.g. Does stack grow upward or downward?
As always, check the C tag wiki and the books list The Definitive C Book Guide and List

printing values of dynamic array

I have made a dynamic array of integers in C, here is my code
#include <stdio.h>
int main(){
int count=0, i, input;
int *myarr;
myarr=(int*)malloc(4*sizeof(int));
while(1){
scanf("%d", &input);
myarr[count]=input;
count++;
if (input == -1) break;
}
for (i=0; i<count; i++){
printf("%d ", myarr[i]);
}
return 0;
}
From the code, I thought i clearly made an array of 4 integers only i.e myarr[0] up to myarr[3], how come when i insert even 10 integers, it still prints all of them, it doesn't print garbage as i thought it would after the fourth integer... Maybe i didn't understand the point of dynamic creating an array?? Make me straight please!
You should only access myarr[0] up to and including myarr[3].
Accessing any other index is undefined behaviour: it might work, it might not.
Also, myarr[count]==input looks like a typo. Did you mean myarr[count] = input? The way you have it is testing if myarr[count] equals input. Technically the way you have it is undefined behaviour for any element of myarr since you are making use of uninitialised data.

Number spiral in C, code not working

I want to make a spiral in C using a 2D matrix, such as the one shown below:
This is the code that I worked out. But it keeps going into an infinite loop. I can't seem to get an output. Can anyone tell me what mistake I'm making in this logic?
And I know its pretty cumbersome, but the assignment is to get the output for any "n" dimensional array, and we need to use all the row_left,row_right, etc variables, as they're given in the question.
#include<stdio.h>
int main(void)
{
int array[6][6]={1},dim,row_right=0,row_left=dim-1,col_up=0,col_down=dim-1;
int i,j,num,cnt;
printf("Enter the dimensions of 2D array:\n");
scanf("%d",&dim);
num=dim*dim;
cnt=0;
while(cnt!=num)
{
for(j=col_up;j<=col_down;j++)
{
if(j=0)
array[row_right][j]=1;
else
array[row_right][j]=array[row_right][j-1]+1;
}
for(i=row_right+1;i<=row_left;i++)
array[i][col_down]=array[i-1][col_down]+1;
for(j=col_down-1;j>=col_up;j--)
array[row_left][j]=array[row_left][j+1]+1;
for(i=row_left-1;i>row_right;i--)
array[i][col_up]=array[i+1][col_up]+1;
row_right++;
row_left--;
col_up++;
col_down--;
cnt++;
}
for(i=0;i<dim;i++)
{
for(j=0;j<dim;j++)
printf("%d\t",array[i][j]);
printf("\n");
}
return 0;
}
if(j=0)
is almost surely wrong. This sets j to zero and always evaluates to a false condition. The correct condition uses j == 0.
Also, the code uses the variable dim before it is read by scanf.
You forgot to initialize the variable dim. That is used in following line :
int array[6][6]={1},dim,row_right=0,row_left=dim-1,col_up=0,col_down=dim-1;
With correctly formatted code you probably would have seen this.

Check whether a pointer points to a empty space on a int array

So, I've got a assignment that asks for me to compare 2 arrays of integers (a[5] and b[8]) and check for repeated elements using pointers.
So far, here's the code I came up with:
int main(void) {
int *pa, i, j, sizeA=5, sizeB=8, a[sizeA], b[sizeB], aux[sizeB];
for (i=0; i<sizeA; i++){
scanf("%d", &a[i]);
}
for (i=0; i<sizeB; i++){
scanf("%d", &b[i]);
}
for (i=0; i<sizeB; i++){
aux[i] = NULL;
}
for(i=0;i<sizeA; i++){
for(j=0; j<sizeB; j++){
if ((a[i] == b[j]))
aux[i] = b[j];
}
}
for(i=0;i<sizeA; i++){
pa = &aux[i];
if ((pa != NULL)&&(*pa!=aux[i+1])){
printf("%d \n", *pa);
}
}
return (EXIT_SUCCESS);
}
It got compiled and run without errors, but when there are no repeated elements, the last for Loop prints strange values such as 435304.
I tried to make the pointer "pa" scan through the array "aux", and only print elements that are different from the next one on the array, and check if the position the pointer is pointing is empty.
Any tips?
EDIT: I solved it initializing the aux array with NULL values. Does it count as a valid solution? Is there a better way to do it?
EDIT2: Thanks to everybody that helped me. Have a nice day.
You only write what's equal on aux, which means that the contents of aux will be a subset of the contents of B, but you're declaring it with sizeB size and not initilizing it's contents. This means that on creation, the contents of aux are all memory garbage. Because, by the subset definition, you'll leave positions of aux without writting (unless A = B), the unwritten positions stay unwritten and so end up containing gargabe. Initialize it to avoid the problem:
int myArray[10] = { -1 }; //all elements to -1
And stop iterating upon finding a -1, or whatever other value you want to use to mark the empty positions.
Your problem is that aux is a stack symbol. Taking the address it offsetted &aux[i] will always return non NULL because it is on the stack. You are taking the address of a predefined array element.
If your intention is to save a pointer in aux then you need to define it as an array of int *
int * aux[sizeB];
memset(aux, 0, sizeof(aux)); // don't forget to initialise it
And when you assign it you assign the address there.
for(i=0;i<sizeA; i++){
for(j=0; j<sizeB; j++){
if ((a[i] == b[j]))
aux[i] = &b[j];
}
}
And in your loop just read the address:
for(i=0;i<sizeA; i++){
pa = aux[i];
if ((pa != NULL)&&(*pa!=*(aux[i+1]))){
printf("%d \n", *pa);
}
}
You should initize aux correctly (c doesn't fill arrays with zeros by default, that's where your strange values come from) and add a counter that counts the numbers of matches you found instead of using i < sizeA in that last loop.
Since you are copying data from b to aux.
if ((a[i] == b[j]))
states that if it is true then copy data. So tell us what are your input?
Since you are not getting common data in both arrays. It is printing Garbage values.
For solution :
Just provide same data in both arrays, and you will get your output.
aux has values which are default
First set all values of aux to 0 or run a counter till the place where aux has been filled

Resources