I have some troubles when using strcpy to copy an array of string inside a double pointer with allocated memory, but i can't understand why i get segmentation fault even if i have previously allocated memory.
Here is the code:
#include <stdio.h>
#include <string.h>
typedef struct Students {
int q_exams;
char **done_exams;
}Students;
int main() {
Students a;
int i;
char support[30];
printf("how many exams have you done ?\n");
scanf("%d",&(a.q_exams));
a.done_exams=malloc(sizeof(char*)*a.q_exams);
if(a.done_exams==NULL)
{
printf("out of memory\n");
return 0;
}
for(i=0;i<a.q_exams;i++)
{
printf("Insert the name of the exam\n");
scanf("%28s",support);
a.done_exams[i]=malloc(strlen(support)+1);
if(a.done_exams[i]==NULL)
{
printf("out of memory\n");
return 0;
}
strcpy(a.done_exams[i][0],support);
fflush(stdin);
}
return 0;
}
You need to pass an address of the initial character to strcpy, either like this
strcpy(&a.done_exams[i][0],support);
// ^
// Add an ampersand
or equivalently like this:
strcpy(a.done_exams[i] , support);
// ^
// Remove the second index
Currently, your code passes the value* of the initial character, rather than its address.
* The value is undefined at the time as well, but it is not the primary cause, because you should not be passing value at all.
This code is fixed
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct Students {
int q_exams;
char **done_exams;
} Students;
int main()
{
Students a;
int i;
char support[49];
printf("how many exams have you done ?\n");
scanf("%d",&(a.q_exams));
a.done_exams = malloc(sizeof(char*) * a.q_exams);
if(a.done_exams==NULL)
{
printf("out of memory\n");
return 0;
}
for(i = 0 ; i < a.q_exams ; i++)
{
printf("Insert the name of the exam\n");
scanf("%48s",support);
a.done_exams[i] = malloc(strlen(support)+1);
if(a.done_exams[i] == NULL)
{
printf("out of memory\n");
return 0;
}
strcpy(a.done_exams[i]/*[0]*/, support);
/* ^ ^- this is wrong
* + pass the address to the array not the first element value
*
* if you had warnings turned on you would have seen this
*/
fflush(stdin);
}
return 0;
}
notice that
scanf("%48s", support);
requires
char support[49];
which is also fixed in the code.
See the man page of strcpy().
The first argument should be of type char *.
As per your code, the argument [a.done_exams[i][0]] is of type char. You need to pass a char * [starting address of the destination] actually.
Change your code to
strcpy(a.done_exams[i],support);
The
strcpy(a.done_exams[i][0],support);
should be
strcpy(a.done_exams[i],support);
or
strcpy(&a.done_exams[i][0],support);
My advice would be to always compile with compiler warnings turned on. My compiler (gcc) does a very good job of catching the problem and telling you exactly what needs to be done to fix it:
test.c:37:12: warning: incompatible integer to pointer conversion passing 'char' to
parameter of type 'char *'; take the address with & [-Wint-conversion]
strcpy(a.done_exams[i][0],support);
^~~~~~~~~~~~~~~~~~
&
P.S. You are also missing some #includes:
#include <stdlib.h>
#include <string.h>
Related
I'm trying to write a data structure with two elements, and then defining a variable of that type struct. However, after initializing the variable in the main function, I'm getting segmentation fault and I don't know why.
#include <stdio.h>
#include <string.h>
struct AnimalSizes {
char stringName[50];
double sizeLength;
} animalSizes[2];
int main()
{
struct AnimalSizes *snakes;
strcpy(snakes[0].stringName,"Anaconda");
snakes[0].sizeLength=3.7;
strcpy(snakes[1].stringName,"Python");
snakes[1].sizeLength= 2.4;
printf("%c", *snakes[0].stringName);
printf("%lf", snakes[0].sizeLength);
printf("%c", *snakes[1].stringName);
printf("%lf", snakes[1].sizeLength);
return 0;
}
You try to strcpy to destination where is no allocated memory. That is undefined behavior.
You should first allocate enough memory to hold two AnimalSizes instances:
struct AnimalSizes *snakes;
snakes = malloc(2 * sizeof(struct AnimalSizes));
Also, here
printf("%c", snakes[0].stringName);
you are trying to output the first character of stringName. I assume, what you rather want to do is to output whole string with %s.
You've declared a pointer to a struct AnimalSizes, and you have declared an array struct AnimalSizes[2], but you have not made the pointer point to this array:
int main()
{
struct AnimalSizes *snakes = &animalSizes[0];
...
}
Alternatively, you may choose to not declare a global variable, rather choosing to allocate memory in main:
#include <stdlib.c>
#include <stdio.h>
#include <string.h>
struct AnimalSizes {
char stringName[50];
double sizeLength;
};
int main()
{
struct AnimalSizes *snakes = (struct AnimalSizes*) malloc(2*sizeof(struct AnimalSizes));
strcpy(snakes[0].stringName,"Anaconda");
snakes[0].sizeLength=3.7;
strcpy(snakes[1].stringName,"Python");
snakes[1].sizeLength= 2.4;
printf("%c", *snakes[0].stringName);
printf("%lf", snakes[0].sizeLength);
printf("%c", *snakes[1].stringName);
printf("%lf", snakes[1].sizeLength);
free(snakes);
return 0;
}
the following proposed code:
eliminates any need for malloc() and free()
performs the desired functionality
separates the definition of the struct from any instance of the struct.
inserts some spacing between the first letter of the snake name and the 'size' of the snake, for readability
applies certain other changes to the code for 'human' readability
and now the proposed code:
#include <stdio.h>
#include <string.h>
struct AnimalSizes
{
char stringName[50];
double sizeLength;
};
int main( void )
{
struct AnimalSizes snakes[2];
strcpy(snakes[0].stringName,"Anaconda");
snakes[0].sizeLength=3.7;
strcpy(snakes[1].stringName,"Python");
snakes[1].sizeLength= 2.4;
printf("%c ", snakes[0].stringName[0]);
printf("%lf\n", snakes[0].sizeLength);
printf("%c ", snakes[1].stringName[0]);
printf("%lf\n", snakes[1].sizeLength);
return 0;
}
a run of the proposed code outputs:
A 3.700000
P 2.400000
i am facing some difficulties with malloc and structs. I want to read the m_data.number_chars as shown in my code (which is an integer) to be the memory that i want to allocate.. But when i compile my code, and run it, it crushes.. Any ideas..? Thanks in advance!
#include <stdio.h>
struct movies {
int number_chars;
char name;
int made_year;
float money;
};
struct movies m_data;
int main()
{
scanf("%d",&m_data.number_chars);
m_data.name=malloc(m_data.number_chars);
gets(m_data.name);
printf("%s",m_data.name);
}
Well you were supposed to pass char* to the scanf - more specifically address of the variable on which input will be stored. You didn't do that.
No return value check for the standard functions and ofcourse you didn't use malloc earlier.
#include <stdio.h>
#include <stdlib.h>
struct movies {
int number_chars;
char* name;
int made_year;
float money;
};
struct movies m_data;
int main(void)
{
if( scanf("%d",&m_data.number_chars)!= 1){
fprintf(stderr, "%s\n", "Error in input");
exit(EXIT_FAILURE);
}
getchar();
if(m_data.number_chars <= 0){
fprintf(stderr, "%s\n", "Error in number of character count");
exit(EXIT_FAILURE);
}
m_data.name = malloc(m_data.number_chars+1);
if(!m_data.name){
perror("Malloc error");
exit(EXIT_FAILURE);
}
if(fgets(m_data.name,m_data.number_chars+1,stdin)){
printf("[%s]\n",m_data.name);
}
return 0;
}
When calling scanf, you need to pass the address of the variable to hold the result (using the ampersand &). This would definitely cause serious memory problems right there.
Also, name is of type char. char is not a pointer. Therefore, you cannot assign the result of malloc() to name.
You need a pointer type.
Also, "crushes" is not a technical description of what is going wrong. You'll probably get further if you can articulate your situation better.
Try:
#include <stdio.h>
#include <stdlib.h>
struct movies {
int number_chars;
char *name;
int made_year;
float money;
};
struct movies m_data;
int main()
{
scanf("%d",&m_data.number_chars);
m_data.name=malloc(m_data.number_chars);
gets(m_data.name);
printf("%s",m_data.name);
free(m_data.name)
}
I was doing some testing for a program of mine and was wondering why the program was crashing when entering my function. Don't mind the logic of the program, since i was still in the phase of making sure i understood how to use my tools at hand.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Constants */
#define HEX_CAPITAL_LETTERS_BEGIN 65
#define HEX_CAPITAL_LETTERS_END 90
#define HEX_NUMBERS_BEGIN 48
#define HEX_NUMBERS_END 57
#define EXIT_SUCCES 0
/* Prototypes */
void codeToField(char *charArray, int i, int hexFloor, int hexCeil, char *outputArray);
/* Main Function */
int main(void) {
char *code, warehouse, product, qualifiers;
int i = 0;
printf("Enter a MMOC product code: ");
scanf("%s", &code);
codeToField(code, i, HEX_CAPITAL_LETTERS_BEGIN, HEX_CAPITAL_LETTERS_END, &warehouse);
codeToField(code, i , HEX_NUMBERS_BEGIN, HEX_NUMBERS_END, &product);
strcpy(&qualifiers, code + i);
printf("\n\nWarehouse: %s\nProduct: %s\nQualifiers: %s\n", &warehouse, &product, &qualifiers);
return EXIT_SUCCES;
}
void codeToField(char *charArray, int i, int hexFloor, int hexCeil, char *outputArray) {
int j = 0;
while (charArray[i] >= hexFloor && charArray[i] <= hexCeil) {
outputArray[j] = charArray[i];
i++;
j++;
}
}
Thanks in advance.
First, this does not do what you want:
char *code, warehouse, product, qualifiers;
The only pointer is code, the other are just a single char. You're printing them as strings with printf, and you use warehouse and product as outputArray in your function. They need to be pointers (or arrays) too:
char *code, *warehouse, *product, *qualifiers;
Then you need memory. The pointers are still uninitialized, so any reading from them is undefined behavior.
You can either allocate memory with automatic storage duration (on the stack) or dynamically (on the heap).
Stack:
char codestr[100];
code = codestr;
but then, you could also just have declared code as
char code[100];
to avoid to have two variables.
If you want to allocate the memory dynamically, you would use malloc:
code = malloc(100);
Don't forget to free the memory again:
free(code);
warehouse, product, qualifiers all need memory too. Some of the array sizes could be deduced form the defined constants.
char *code, warehouse, product, qualifiers;
int i = 0;
printf("Enter a MMOC product code: ");
scanf("%s", &code);
Here, code is an uninitialized pointer to memory so once you do the scanf call, your program is hosed.
I think you want something more like
char code[100];
printf ("Enter a MMOC product code: ");
scanf ("%s", code);
The reason is because code has no memory allocated to it. It is an uninitialized pointer. Try this instead:
// ...
char myString[16], *code, warehouse, product, qualifiers;
code = &myString[0];
int i = 0;
printf("Enter a MMOC product code: ");
scanf("%15s", code);
// ...
Although I think I have more than one issue in this code, I want to solve my compiler error first. Thank you in advance for any suggestions. I will try to address run errors next.
The Error:
fuzzer.c: In function ‘main’:
fuzzer.c:26:25: warning: assignment makes integer from pointer without a cast [-Wint-conversion]
charArray[arraySize-1] = NULL; /*make sure charArray[] is a string array that has a size of arraySize */
^
The Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <time.h>
int main(void)
{
int fuzzNum = 100;
char buffer[1000], *charArray;
int status, ret, i, j, retCode, arraySize; /* */
time_t t;
FILE *fin;
FILE *fout;
srand((unsigned) time(&t)); /* randomize the initial seed */
for(i=0; i<fuzzNum; i++)
{
charArray = (char *) malloc(arraySize);
for (j=0; j< arraySize; j++)
charArray[j] = 'A';
charArray[arraySize-1] = NULL;
/*make sure charArray[] is a string array that has a size of arraySize */
/* open and read the cross.jpg file as a binary format file*/
fin=fopen("./cross.jpg","rb" );
/*generate a variable file name*/
char fileName[30]; int n;
sprintf(fileName, "crashed-%d.jpg", n);
fout=fopen("./test.jpg","wb");
/* execute the jpg2bmp file to process the test.jpg file*/
char comBuf[200];
sprintf(comBuf, "./jpg2bmp test.jpg temp.bmp");
ret=system(comBuf);
free(charArray); /* must free memory for repeat testing! */
ret=system(buffer);
wait(&status);
retCode=WEXITSTATUS(ret);
if ( retCode == 128+11 || retCode ==128+6) /* segmentation fault (11) or Abort (6) */
{
printf("retCode=%d, arraySize = %d", retCode, arraySize);
fflush(stdout); /*make sure output is print out immediately ! */
}
}
return 0;
}
First of all, this is a warning, and not an error. Your code should compile successfully in the least, if this warning is the only issue the compiler produces during the build process. However, if you want to overcome this issue, you can simply change:
charArray[arraySize-1] = NULL;
To:
charArray[arraySize-1] = 0;
While charArray is a pointer that points to the first memory space in the array, charArray[i], where i represents a counter as an example here, is of data type int. Now, NULL is used when a pointer points to nothing, or in computer terms, to the ground. Therefore, the compiler warns you that you are storing a pointer attribute in a non-pointer memory space (Sorry for the really por choice of words, if there is anything wrong with it, please correct me in the comments box).
The above code change should resolve the warning your compiler produces.
I'm having trouble with pointers. I know I should have gone to office hours, but I'm in desperate need of help. The biggest problem right now is trying to debug this program. From my understanding, I'm supposed to declare an address in my void functions. After, I have to use & for readfile(%testarray). What am I doing wrong? The objective of my program is to read a file of numbers and store them in an array. Then, I would print all of the numbers in my array. Any help would be greatly appreciated.
sort.c:11:3: warning: passing argument 1 of 'read_file' makes pointer from integer without a cast [enabled by default]
sort.c:3:6: note: expected 'int **' but argument is of type 'int'
sort.c: In function 'read_file':
sort.c:27:3: warning: format '%d' expects argument of type 'int *', but argument 3 has type 'int' [-Wformat]
Code:
#include <stdio.h>
#include <stdlib.h>
void read_file(int* myList[]);
int main()
{
int testarray[20];
read_file(&testarray[20]);
return 0;
}
void read_file(int* myList[])
{
FILE* inFile;
int i;
inFile = fopen("data.txt","r");
if (inFile == NULL)
{
printf("Unable to open file");
exit(1);
}
i = 0;
while (fscanf(inFile,"%d", *myList[i]) != EOF)
{
printf("%d ", *myList[i]);
i = i+1;
}
printf("\n");
printf("%d\n", i );
} //void
When you use square brackets [] after a name in a function header, you tell the compiler that you are passing an array.
int testarray[] means an array of integers
int *testarray[] means an array of integer pointers
Since you pass an array of integers, the function signature should be either
void read_file(int myList[]);
or its equivalent
void read_file(int *myList);
The call should look like this:
read_file(testarray);
Next, on the subject of & vs. *: ampersand makes a pointer from an value expression that has an address, while an asterisk makes a value from a pointer expression. scanf takes a pointer, so you need to call it with either
fscanf(inFile,"%d", &myList[i])
or an equivalent
fscanf(inFile,"%d", myList+i)
You should be using:
read_file(&testarray);
As you try to pass a pointer to the whole array. What you have done simply takes the address of the 20-th element in the array(which is out of bounds btw).
Here is your fixed code.
#include <stdio.h>
#include <stdlib.h>
void read_file(int myList[20]);
int main()
{
int testarray[20];
read_file(testarray);
return 0;
}
void read_file(int myList[20])
{
FILE* inFile;
int i;
inFile = fopen("data.txt","r");
if (inFile == NULL)
{
printf("Unable to open file");
exit(1);
}
i = 0;
while (fscanf(inFile,"%d", &myList[i]) != EOF)
{
printf("%d ", myList[i]);
i = i+1;
}
printf("\n");
printf("%d\n", i );
}
The expression &testarray[20] is a pointer to one beyond the last entry in the array (i.e. the same as int *), which is not the same as a pointer to an array. And besides, you now declare the argument to be an array of pointers, not a pointer to an array. (difference between int *arr[] and int (*arr)[]).
Also, you don't need to pass a pointer to the array to the function, instead just let the function have a normal array (or pointer) argument, and pass the array as-is:
void read_file(int myList[]);
int main(void)
{
int testarray[20];
read_file(testarray);
/* .... */
}
Inside the read_file you don't need the dereference operator * when using the array. You can use it as a normal array.
Assuiming 10 numbers in the text file, refer the following code :
#include <stdio.h>
#include <stdlib.h>
void read_file(int *);
int main()
{
int *List=(int *)malloc(10*sizeof(int));// Allocate memory for 10 integers
read_file(List);
return 0;
}
/* Passing a pointer to the contiguous locations, just the starting location is enough*/
void read_file(int *ptr)
{
FILE *inFile;
inFile=fopen("Numbers.txt","r");
int i=0;
if(inFile!=NULL)
while(fscanf(inFile,"%d",ptr)!=EOF)
{
printf("%d ",*(ptr));
i++;
}
free(ptr);// Free the memory Locations
}