Array of Char pointers (strings) crashes after input? - c

I want to store an array of strings , count their length and re-arrange them with length-increasing-order (smallest->larger) using the algorithm mentioned below //
Swap holds a relatively big string to replace the order (when another min is found)
I could use realloc() but I am not considering defend programming yet
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i,j,N;
printf("\n Input amount of alphanumericals: ");
scanf("%d",&N);
{
int min;
char *swap=(char*)malloc(sizeof(char)*150);
char *A[N],**temp;
temp=A;
for(i=0;i<N;i++){
printf("\nInput %d element:",i+1);
fgets(temp+i,150,STDIN);
}
printf("\n\nData [");
for(i=0;i<N;i++)
printf(" %s",A[i]);
printf(" ]\n\n");
//Ins sort
for(i=0;i<N;i++){
min=i;//Assume current is min
for(j=i+1;j<N;j++){
//Compare assuming min with current
if(strcmp(A[j],A[min])<0){
min=j;
}
//If next is min replace in current position
if(min!=i){
swap=A[i];
A[i]=A[min];
A[min]=swap;
}
}
free(swap);
printf("\nAfter insertion point algorithm\n");
printf("\n\nInsertion Sorted Data [");
for(i=0;i<N;i++)
printf(" %s",A[i]);
printf(" ]");
}
return 0;
}

You are tying to free memory that has not been allocated using malloc:
char *A[N],**temp;
temp = A; // A is an automatic (AKA "stack") variable; now temp points to it as well
free(temp); // Undefined behavior
Inside the loop you are reading with gets into strings that have not been allocated:
gets(temp+i); // That's the same as gets(A[i]); Your A[i]s are unallocated.
As a side note, you should not use gets, because it is a prime source of buffer overruns. Use fgets instead, and pass stdin as the FILE* parameter. scanf with %20s is another alternative to limit the size.
In addition, since i goes from 1 to N, inclusive, this expression references one element past the A array on the last iteration:
gets(temp+i); // Undefined behavior when i==N
EDIT : Why is the code below crashes?
for(i=0;i<N;i++){
printf("\nInput %d element:",i+1);
fgets(temp+i,150,STDIN);
}
The code below crashes because you did not allocate memory for the individual strings:
for(i=0;i<N;i++){
printf("\nInput %d element:",i+1);
temp+i = malloc(151); // No need to multiply by sizeof(char) or cast to char*
fgets(temp+i,150,STDIN);
}
Note that you need to allocate one extra char for the null terminator.

You are not using gets correctly: take a look at its manual page [1]. Moreover, using gets is not recommended: better use fgets.
Also, gets is not allocating the string for you, so when you pass it a char * pointer, the pointer has to point to a valid memory location. Instead, your A[n] is an array of dangling pointers.
Then, why free(temp)? You must call free for each pointer allocated with malloc: not the case for temp.
Finally, please format your code: use indent.
[1] http://linux.die.net/man/3/gets

Related

Memory Allocation In C , Use of Realloc

How do i use realloc function for calloc here. please guide ??
the first input of calloc function is giving me the right output but after using the realloc function my compiler just stuck , what mistake Am I doing here?
OUTPUT IS GIVEN:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int n,n2,sum=0,i;
int *ptr,*p;
printf("Enter Totoal Number of elements:");
scanf("%d",&n);
ptr=(int*)calloc(n,sizeof(int));
for(i=0;i<n;i++)
{
printf("Enter %d Element:",i+1);
scanf("%d",ptr+i);
sum=sum+*(ptr+i);
}
printf("The sum is: %d\n",sum);
printf("Enter new size:");
scanf("%d",&n2);
p=(int *)realloc(ptr,n2*sizeof(int));
for(i=0;i<n2;i++)
sum=sum+*(p+i);
printf("The new sum is:%d",sum);
free(ptr);
free(p);
}
OUTPUT HERE
Edit after update: you are double freeing the same pointer.
free(ptr);
free(p);
According to man realloc: realloc returns the pointer passed as argument, so ptr and p are the same. Actually you don't need two pointers here.
If you want to initialise go through ptr instead or p, which is what I guess you try to do then:
for(i=0;i<10*sizeof(int);i++)
You are looping 10 * sizeof(int) times to go through an array of size 10, accessing *(ptr+i) is like accessing ptr[i], ptr+i evaluates to the address ptr + sizeof(*p), you can read about pointer arithmetic if you want to learn more.
In your case, you are going out of bounds of your allocated memory, because your dynamically allocated array has size 10.
You simply do not reset sum to zero.
printf("Enter new size:");
scanf("%d",&n2);
p=(int *)realloc(ptr,n2*sizeof(int));
for(i=0;i<n2;i++)
sum=sum+*(p+i);
printf("The new sum is:%d",sum);
Before you ask for new size, you have already summed up the n entries.
Then you add on top of that the first n2 entries.
If you want to cound only the n2 entries, simply set sum=0; before you add up again.
Also You code will break if n2 > n as you do not provide new values for the new entries.
Another error:
free(ptr);
free(p);
You are not allowed to use ptr after you called realloc. It might have been free'd already in realloc if the memory location needed to be moved. Then that memory is not your's any more.
Or it might be same as p, then you will try to free the samem memory twice.
Both are no good ideas.

pointer int in C, need help understanding and simplifying code snippet

I just wrote this snippet of code and have passed values of integers in for when it scans the integer in, but am getting back the memory address of the int towards the end.. how do I display only the number that I just read in instead of it's address? Can I simplify this code snippet even more?
#include <stdlib.h>
#include <stdio.h>
typedef struct building {
char *blockName;
int blockNumber;
} building;
int main() {
building *blockA = (building*)malloc(sizeof(building));
building *blockB = (building*)malloc(sizeof(building));
blockA->blockName = (char*)malloc(25*sizeof(char*));
blockB->blockName = (char*)malloc(25*sizeof(char*));
blockA->blockNumber = (int)malloc(sizeof(int));
blockB->blockNumber = (int)malloc(sizeof(int));
printf("What is the name for your first block: ");
scanf("%s", (*blockA).blockName);
printf("What will be it's number: ");
scanf("%d", (*blockA).blockNumber);
printf("\n");
printf("What is the name for your second block: ");
scanf("%s", (*blockB).blockName);
printf("What will be it's number: ");
scanf("%d", (*blockB).blockNumber);
printf("\n");
printf("Your first block's name is %s. It's number is %d\n", (*blockA).blockName, (*blockA).blockNumber);
printf("Your second block's name is %s. It's number is %d\n", (*blockB).blockName, (*blockB).blockNumber);
printf("\n");
free(blockA->blockName);
free(blockB->blockName);
free(blockA);
free(blockB);
system("pause");
return 0;
}
The member
int blocknumber;
is a plain scalar integer, not a pointer. Use it directly, without allocating memory to it. This line:
blockA->blockNumber = (int)malloc(sizeof(int));
is very suspicious and your compiler should have warned you. (You do compile with warnings enabled, don't you?) You are tyring to store a pointer in an integer value, which will fail on machines where the size of a pointer is greater then the size of an int.
The remedy is not to allocate memory for a scalar, then
scanf("%d", &(*blockB).blockNumber);
(note the &), and then you will have the user input available as:
printf("It's number is %d\n", (*blockB).blockNumber);
On the other hand, the malloc for the string is right, because the string is an array of chars, in this case allocated on the heap and represented by a pointer to the first char.
Since building is defined as
typedef struct building {
char *blockName;
int blockNumber;
} building;
You shouldn't be doing this
blockA->blockNumber = (int)malloc(sizeof(int));
as the line building *blockA = (building*)malloc(sizeof(building)); will already have allocated space on the heap for the int blockNumber:
You can simply assign it
blockA->blockNumber = 1234;
Or prompt the user for it
scanf("%d", &(blockA->blockNumber));

Arrays and Pointers, which is the better way to write in similar situations

Is there anyway to write the code without having to initialise the size of the array?
#include <stdio.h>
#define MAXSIZE 100
int main()
{
int i,n;
int num[MAXSIZE];
printf("Enter the value of n\n");
scanf("%d",&n);
printf("Enter the list of integers\n");
for(i=0;i<n;i++);
scanf("%d",&num[i]);
for(i=0;i<n;i++)
printf("%d\t",num[i]);
return 0;
}
I used MAXSIZE since the compiler required me to initialise the size, an error came up everytime I left the size blank. All this because incase the user wants to input more than 100 values, how do i accomodate him?
Is using pointers a better way to write the program?
I tried by changing
#include<stdio.h>
int main()
{
int *num,n,i;
printf("Enter the value of n\n");
scanf("%d",&n);
printf("Enter the list of integers\n");
for(i=0;i<n;i++);
scanf("%d",num+i);
for(i=0;i<n;i++)
printf("%d\t",*(num+i));
return 0;
}
This is giving me a warning saying uninitialised local variable in visual studio and isn't inputting all the numbers. Output is garbage values.
Dev c++ crashes everytime I execute.
Any advice would be helpful, Thanks in advance guys.
If you are using a compiler that supports variable-length arrays (C99 or later, although VLAs are now optional under C2011) and the size of the array is relatively small, you can do the following:
int i, n;
...
scanf( "%d", &n );
int num[n];
// load and print num as before
If your compiler does not support VLAs or the array size is large (more than a few hundred K), then you will want to allocate memory dynamically using either malloc or calloc:
int i, n;
...
scanf( "%d", &n );
int *num = malloc( n * sizeof *num );
// load and print num as before
When you use just a plain pointer, you still need to allocate memory for the array. We can do that with malloc!
int *num,n,i;
printf("Enter the value of n\n");
scanf("%d",&n);
num = malloc(sizeof(*num) * n);
printf("Enter the list of integers\n");
...
Also, even though you are using pointers, you can still write num[i] instead of *(num +i). In fact, those two expressions are always interchangeable, and so you you should use the one that makes your code the most readable.
You can use variable length arrays if you want user to put the size of array (run program in C99 ode. Use the option: -std=c99).
Arrays are used when you need small memory. If you need some large amount of memory then go with pointers and dynamic allocation. When using pointer, initialize it to some memory location before any access to it.
Arrays are NOT pointers !
Their types types are completely different and are treated differently by the compiler.
int *num ;
declares num as pointer to int, which is not pointing to any valid memory address
("uninitialized" as reported by compiler ) . Whatever operation you're doing in second case invokes undefined behaviour
You need to point it to a valid memory location, in this case by using malloc call
num = malloc( sizeof( int ) * n);

Organizing string of int - using debugger

as i stated before, i am learning C from home, and hitting some bumps on the way. Thanks to you all i am learning bit by bit.
I wrote something that made sense in my head and taking in account what i've learned so far:
int exercicio4a(int *s){
int tmp, i;
int nmax = strlen(s);
int z[nmax];
for(i=0; i!=nmax; i++){
if(s[i]>=s[i+1]){
z[i]=s[i+1];
}else{
z[i]=s[i];
}
}
return z;
}
main(){
int x, y, nmax;
int str[10];
printf("Organize a bunch of numbers:\n");
nmax = 9;
while(nmax!=0){
printf("Enter the random int number %d :\n", nmax);
scanf("%d", &str[nmax]);
nmax--;
}
printf("%s \n", exercicio4a(str) );
}
Needless to say that this is garbage as it doesn't take me anywhere!
One last thing, i would like to know if there is a way to use GDB in order to detect a malfunction in this code for example.
Cheers!
Well, you need to clarify your terms. You want to sort an array of integers, which you scan from stdin, I assume. Don't call this array a string, it is bad terminology. You also need to decide if exercicio4a should return a string of ascii characters, where the integers are inserted into a string, or an array of integers.
You really should be taking an integer array for your function and either sorting in place, or allocating a new one and returning it.
Now let's look at the problems with your code:
nmax = 9;
while(nmax!=0){
printf("Enter the random int number %d :\n", nmax);
scanf("%d", &str[nmax]);
nmax--;
}
You are exiting the loop when nmax == 0, but you never scan an integer into that location. To fix this:
nmax=10;
while (nmax--) {
//printf
scanf("%d", str + nmax); //or &str[nmax]; these are equal
}
Next: int exercicio4a(int *s){... This signature is incorrect. Assuming you don't want to sort in place, you want to return a new array so you should have int *exercicio4a(int *s){... You want to return a pointer to the first integer in the array.
Next int z[nmax]; This array is a local variable. It will go out of scope when you return from the function so the behavior of using it after you return is undefined! Instead you want to dynamically allocate space for the sorted array using int *z = calloc(nmax, sizeof(int)); You will need to free the returned array after the calling function is done using it to avoid memory leaks.
Next: printf("%s \n", exercicio4a(str) ); Here you are trying to print an integer as a string (with the code you have). Even if you fix it to return an int* you will still be trying to print an array of integers as a string. What you should do is use a loop to print the array:
nmax = 10;
int *ptr = exercicio4a(str); //only after you fix exercicio
while (nmax--)
printf("%d ", *ptr++);
Lastly, your loop does not perform a sort. It is an attempt to swap adjacent elements that are out of order. It does not perform this functionality correctly, but don't bother getting that working since it won't even implement a sorting algorithm. I suggest you read about insertion, bubble, and selection sort to get a feel for how to implement those algorithms if you want to learn how to do sorts on your own. Most of the time though, you will want to use a library function to sort an array. If you want to keep an un-sorted copy of your data, make a qsort wrapper:
int compare (void *one, void *two) {
return *(int *)one - *(int *)two;
}
int *my_sort(int *arr, int size) {
int *sorted = calloc(size, sizeof(int));
memcpy(sorted, arr, size * sizeof(int));
qsort(sorted, size, sizeof(int), compare);
return sorted;
}

How to expand a one-dimensional array at runtime in C?

I'm learning C language and I have a question about dynamic memory allocation.
Consider that I have a program that the user must enter numbers or typing the letter "E" to exit the program.
The numbers that the user enter must be stored in a one-dimensional array. This array begins with a single position.
How can I do to increase my array of integers to each number that the user enters to store this number in this new position? I think I must use pointers correct? And then, how do I print the values ​​stored in the array?All the examples I find are complex to understand for a beginner. I read about the malloc and realloc functions but I don't know exactly which one to use.
Can anyone help me? Thanks!
void main() {
int numbers[];
do {
allocate memory;
add the number to new position;
} while(user enter a number)
for (first element to last element)
print value;
}
If you need to expand an array at runtime, you must allocate memory dynamically (on the heap). To do so, you can use malloc or more suitable for your situation, realloc.
A good example on this page here, which I think describes what you want.: http://www.cplusplus.com/reference/cstdlib/realloc/
Copy pasted from the link above:
/* realloc example: rememb-o-matic */
#include <stdio.h> /* printf, scanf, puts */
#include <stdlib.h> /* realloc, free, exit, NULL */
int main ()
{
int input,n;
int count = 0;
int* numbers = NULL;
int* more_numbers = NULL;
do {
printf ("Enter an integer value (0 to end): ");
scanf ("%d", &input);
count++;
more_numbers = (int*) realloc (numbers, count * sizeof(int));
if (more_numbers!=NULL) {
numbers=more_numbers;
numbers[count-1]=input;
}
else {
free (numbers);
puts ("Error (re)allocating memory");
exit (1);
}
} while (input!=0);
printf ("Numbers entered: ");
for (n=0;n<count;n++) printf ("%d ",numbers[n]);
free (numbers);
return 0;
}
Note that the size of the array is remembered using countvariable

Resources