malloc for char pointers and printf [closed] - c

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I have a file which looks like following:
ATOM HIS
ATOM TRP
ATOM PHE
I want to print the first column, following is my C-code:
#include<stdio.h>
#includ<stdlib.h>
void main
{
FILE *fp;
fp=fopen("xyz","r");
char *atm,*res;
char buff[200];
while(fgets(buff,sizeof (buff),fp)!=NULL){
i++;
}
rewind(fp);
atm=(char*)malloc(i * sizeof (char*));
res=(char*)malloc(i * sizeof (char*));
while(fgets(buff,sizeof (buff),fp)!=NULL){
fscanf(fp,"%s %s",&atm[i],&res[i]);
i++;
}
for(j=0;j<i;j++){
printf("%s\n",atm);
}
I would expect the following output:
ATOM
ATOM
ATOM
But it doesn't compile and says that:
warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’
hence in printf statement I have added & to atm (i.e &atm instead of atm). In this case the code compiles well but gives the following output:
AAAAAAAAAAAAAAAATOM
AAAAAAAAAATOM
AAAAAAAATOM
I will appreciate any suggestion regarding this.

First of all,
atm=(char*)malloc(sizeof (char*));
does not do what you think it does. It only allocates a memory enough o hold a char *, that's also wrongly.
You need to allocate a size of n * sizeof(char), where, n == number of chars. Now, sizeof(char) == 1 being guaranteed by C standard, your statement can be reduced to
atm = malloc(requiredsize);
res= malloc(requiredsize);
After that, you should check for the success of malloc() call to prevent UB from accessing NULL pointer.
But then, you'll be overwriting atm and res in every call to fgets() and fscanf(). You seem to need an array of pointers, not a simple pointer to get the job done.

If atm and res are pointers to arrays of char *, which seems like the intention, then they should be declared as such:
char **atm,**res;
You then need to allocate storage for each string, as well as the array as a whole:
while(fgets(buff,sizeof (buff),fp)!=NULL){
atm[i] = malloc(200); // choose a suitable maximum size
res[i] = malloc(200);
fscanf(fp,"%s %s",atm[i],res[i]);
i++;
}
This much more closely matches your intention - I think.
It's not particularly good practice, however. Using fscanf with %s, there is no guarantee that the string you read won't be longer than what you've allocated (I think you can use a width specifier to limit what it reads, eg %100s, but that limits how much is read as well as how much is stored). You should also check the return from malloc in each case to make sure it was successful.

Related

The printf function in C is not working as intended [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
Can someone help me with this issue? For some reason, no matter what I try, doing printf isn't printing in my code. I've been trying to use the flush method, but that seems to just cause other issues. Is there anything else I can do?
int main(void) {
char **line;
size_t bufsize=MAXBUF;
printf("Type your name: ");
getline(&line,&bufsize,stdin);
}
You are trying to pass in an empty pointer, this pointer isn't pointing to any meaningful address at the start of the program. So the problem with this is that even if you were successful, it would overwrite some random address in memory with the input, and this is almost certainly what you don't want as it will cause a segmentation fault or a crash.
However that's not the reason why it's not compiling. It's not compiling because you are trying to pass in char *** to a function that expects char **.
So what I would do is:
#include <stdio.h>
int main(void) {
char *line=NULL;
size_t bufsize=0;
printf("Type your name: ");
if(getline(&line,&bufsize,stdin)==-1){
puts("Error: User cancelled input.");
}
else{
printf("Entered: %s",line);
}
free(line);
return 0;
}
So what this code does is that it creates a pointer to an array of characters but it sets the pointer to point to NULL so that the program can see it's not pointing anywhere, and then its address (&line) is given to the getline function, this turns the char * type into a char ** which is required by the getline function. Whenever you put a & in front of something in C, it adds an extra * to the type.
You probably know this already, but if a function states that it returns something, you should always return something, even if it's nonsense otherwise depending on the type that should be returned, that can sometimes cause a crash.
There was nothing wrong with your use of printf, that was fine. printf doesn't necessarily fflush to stdout, often the \n character will trigger a flush, but it's implementation specific, so if your program crashes before an fflush is written to stdout, then you may never see the last printf. You can try an fflush(stdout); before the getline function, but after the getline function may not work because it may crash before then.
In your case what's happening is that before the printf writes to the screen the getline takes in the address of the pointer (or pointer to a pointer), dereferences it to a pointer, isn't able to, so before you have a chance to enter in any keystrokes it crashes, losing the stdout pipe, so you end up never seeing your prompt.
When i run the altered code, above, i get:
XXXX#dell:~$ gcc Deleteme.c
XXXX#dell:~$ ./a.out
Type your name: test1
Entered: test1
XXXX#dell:~$
And it runs correctly under Linux. The key lesson in all this is that, terminals are slow to update on the screen, so some time in the past, the decision was made to separate out the functionality of printf.
There are two components to printf:
The part that writes the text to stdout.
The part that updates the terminal with stdout (the flush).
This question is interesting because 1) succeeded, but the system crashed before 2) was completed.
The documentation for getline says the first parameter must be a char **, but you pass it the address of line. Since line is a char **, &line is a char ***, which is the wrong type.
getline() allocates and re-allocates memory. The address of the length and the buffer need to reflect that.
int main(void) {
char *line = NULL;
size_t bufsize = 0;
printf("Type your name: ");
fflush(stdout); // Flush output before reading.
ssize_t len = getline(&line, &bufsize, stdin);
if (len < 0) Handle_error_with_code();
...
free(line); // When done, free memory
}
There is no need to allocate any memory before calling getline().
getline() expects line, bufsize to reflect allocated data via malloc() and friends. It is easy enough to start with NULL, 0 here.
First you are passing the address of line to the getline(), the documentation says that the first argument is the address of the first character position where the input string will be stored. It’s not the base address of the buffer, but of the first character in the buffer.
This pointer type (a pointer-pointer or the ** thing) causes massive confusion.
second your line pointer does not point to anything this should fix it:
char *line = (char *)malloc(bufsize * sizeof(char));
now line is pointing to valid memory address which we requested via malloc() function.

Segmentation Fault by trying to access binary file [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
My program stores matrix in binary files, when I try to "load" them during the same use of the program, everything works well.
However, when I close the program and use it later, it's impossible to access to the same files and I get a Segmentation fault (core dumped) error.
Here's the function that "loads" the matrixes :
void Loading(int mat**){
char* name = malloc(sizeof(char)*20);
printf("Enter name of the file");
scanf("%s",name);
FILE* file=fopen(name,"rb");
if (file==NULL){
printf("error opening file");
exit(0);
}
fread(mat,sizeof(int)*M*M,1,file);
fclose(fichier);
}
where M is a constant.
Again it works perfectly when I store/load mutliple times during the same use of the program
sorry for the mistakes I am not an english speaker
As presented, the question is missing key elements to allow a full analysis, nor a complete answer. But with what is shown, here are some suggestions:
1) The reason(s) for your segmentation fault cannot be identified with absolute certainty because some of the pieces are missing from your post. However, given the fact that it works sometimes, and not others, suggests undefined behavior is playing a part. If I were to guess at the source of undefined behavior, it would be that you are passing around a double pointer variable int **mat, when only a single pointer variable int *mat is necessary (see prototype of fread() below.), further leading me to believe that memory for mat has not been correctly created. I suggest changing:
void Loading(int mat**) // double pointer is not needed here
to
void Loading(unsigned int mat*) //and memory allocation method adjusted accordingly.
(See reason for unsigned in 3) below.)
2) The prototype for the function fread() is:
size_t fread (void *Buffer, size_t Element_Size, size_t Number_of_Elements, FILE *Stream);
In your call:
fread(mat,sizeof(int)*M*M,1,file);
Arguments 2 & 3 appear to be reversed. It should probably be written:
fread(mat, sizeof(unsigned int), M*M, file);
3) Why unsigned int verses int when working with binary data?:
Your post is not explicit on how the data is written to the file, or exactly what format it is in, but generally, when working with binary data, it is better to stick with unsigned types for the reasons listed here.
You have a pointer to your buffer for matrix int **mat.
The problem is, that this doesn't point to single continuous place in memory.
int mat** is a pointer to array of pointers to int. This is a place in memory that should contain more pointers one stored after another. Each of them (int*) then should point into different arrays, that would finally contain array of integers.
Basically you use command fread to write whole data into the array of pointers. Maybe you don't have enough space to store your data at all. Even if you would, you need another kind of pointer.
If you have one continuous array, you could point to it using int *. Then you would pick some element by calculating an index.
int *mtx = (int*) malloc(M*M*sizeof(int);
int x = 2, y = 3;
int index = y*M+x;
mtx[index] = 123; // write to matrix coordinates 2,3
You could use fread with this kind of buffer with no problem, just check how are matrix elements indexed in your input file, maybe the x,y is swapped.

Why am I getting warnings when returning array from a function?

I've seen a few examples of returning array from function on stackoverflow. I followed those examples but i am still getting warnings.
#include <stdio.h>
#include <stdlib.h>
char * getNum();
int main(){
int * num;
int * i;
num = getNum();
puts(num);
return 0;
}
char * getNum(){
FILE * fp;
fp = fopen("number", "r"); //getting a 1000 digit number from a file
char * n; //putting it in "array"
n = (char *)malloc(1000 * sizeof(char));
char x[100];
int i, j = 0;
while(!feof(fp)){
fgets(x, 100, fp);
for(i=0; i<50; i++){ //getting the first 50 characters in a line
n[j] = x[i]; //to avoid "new line"
j++;
}
}
fclose(fp);
n[1000] = '\0';
return n;
}
puts(num) gives the right number should I just ignore the warnings?
Why are they popping up?
I hope this isn't considered a duplicat.
cc 8.c -o 8
8.c: In function ‘main’:
8.c:11:9: warning: assignment from incompatible pointer type
num = getNum();
^
8.c:12:10: warning: passing argument 1 of ‘puts’ from incompatible pointer type
puts(num);
^
In file included from 8.c:1:0:
/usr/include/stdio.h:695:12: note: expected ‘const char *’ but argument is of type ‘int *’
extern int puts (const char *__s);
^
The problem is that you seem to be assigning the result of calling getNum to a variable of type int *, which doesn't make much sense as getNum returns a char *.
You also try to print with puts that variable of type int *, while puts accepts only a const char *.
What's more, you're getting out of bounds in your function's code, as I've already mentioned in the comments: n = (char *)malloc(1000 * sizeof(char)); allocates memory for exactly 1000 characters. n[1000] = '\0'; tries to access the 1001st (!) character. Remember, the array indices start from zero!
n = (char *)malloc(1000 * sizeof(char)); // ugly code
That should really be
n = malloc(1000);
if (n==NULL) {perror("malloc"); exit(EXIT_FAILURE);};
because sizeof(char) is always 1, and because you should not cast (in C) the result of malloc, and because malloc can fail and you should test against that.
Then you do later
n[1000] = '\0'; // wrong code
This changes the 1001-th byte (not the last 1000-th one), so is undefined behavior (it is a buffer overflow). You should be really scared, bad things could happen (and if they don't, it is because you are unlucky). You probably want
n[999] = '\0'; // the 1000th byte
BTW, I guess you are using GCC or Clang on some POSIX like system. You really should take the habit of compiling with all warnings and debug info:
cc -Wall -g 8.c -o 8
(If using make you probably want CFLAGS= -Wall -g in your Makefile)
You might want to learn more about instrumentation options, e.g. you could also pass -fsanitize=address to gcc
Then you can use the gdb debugger and perhaps also valgrind. But be sure to improve your own code till you get no warnings.
Of course num = getNum(); is incorrect. You are assigning a pointer into an integer (so you have a type mismatch). That is often wrong (and in the rare cases -not here- you would really mean it, you should have some explicit cast to show to the reader of your code - perhaps you next year - what you really wanted to do).
You want to convert a string to a number. Read more the documentation of the C standard library. You want to use atoi (type man atoi in a terminal, or read atoi(3)) then code:
num = atoi(getNum());
You are also coding:
while(!feof(fp)) // bad code
This is wrong (and a bit tricky, see this). feof is only valid after some read operation (and not before, see feof(3)). since you want to remove the ending \n (but read fgets(3) & strchr(3)...) you probably want instead
do {
if (NULL==fgets(x, 100, fp)) break;
char*eol = strchr(x, '\n');
if (eol) *eol = 0;
} while (!feof(fp));
at last your code is also incorrect because malloc is not initializing the returned memory zone. So your n might have a zero byte in some unexpected place.
Perhaps you should read about the (POSIX specific) strdup(3) or getline(3). Both could make your code simpler. And think about the adverse situation of files with very long lines (you might have a file with a line of many thousand bytes, and you could even have a file without any newlines in it).
Your puts(num) is also wrong, since also a type mismatch. Consider using printf(3) (but take the habit of ending the control format string with \n or else use fflush(3) because <stdio.h> is buffering), so printf("%d\n", num);
The problem is that you are assigning a pointer of type char * to one of type int *, hence "INCOMPATIBLE" pointers.
You also attempted to pass the int * pointer to puts() which expects a char * pointer, thus there is another warning.
Why are you doing this? If they are clearly pointers of different type it's very strange that you attempted it anyway.
It would be interesting to know, if you think this is correct for some reason.
You need to carefully read warnings and try to understand what they mean, it would help you learn a lot of the basics and good practice too.
Also, please note that: while (!feof(fp)) is not a good way to check if there is nothing else to read because fgets() needs to fail first (to attempt a read after EOF) so you still do the for (i ...) loop after the bad read. You should change to while (fget(x, 100, fp) != NULL)
Finally, in c there is no need to cast void * to any other poitner type, and it's considered bad practice to cast the return value of malloc() because of the reasons explained in this answer

How to resolve a variable for char length? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
EDIT
i want to create a program which will work with a long number. the user will be asked to input the length (in digits) of the number they want to work with. there is a
char aa [the chosen length goes here];
where in the [] brackets should be the value that was input by the user.
it could look like this:
"please input the length in digits"
there is a scanf and you input, for example, 17
then a char aa [17] is created
i just don't know how can i use a variable to input a value in the [] brackets defining the memory size that is saved for a char
You want a variable lenght array, you can do it like this:
int digit;
scanf("%d", &digit);
char test [digit+1];
This will work for your purposes. Usual restrictions of course apply.
Keep in mind this functionality was only added in the C99 Standard. So if your compiler supports only previous standards, this will not work.
However, the more appropriate and better practice method to use is to use malloc to allocate the char array properly
int digit;
scanf("%d", &digit);
char* aa = malloc(digit + 1);
//Do what you want with the char array aa
free(aa);
Do not forget to check the result of malloc() against NULL and free the variable afterwards to prevent memory leaks if you want to do this.
Also be aware that the "array" malloc returns is actually just a pointer, which is very relevant when trying to determine the size/length of it, using sizeof:
char real_array[5];
sizeof(real_array); // == 5
char* dynamic_array = malloc(5);
sizeof(dynamic_array) // == sizeof(char*) == on most systems = 8
What you are asking is variable length array which is possible in C99. See Dynamic array allocation on stack in C
Look at the following code snippet:
int size;
scanf("%d", &size);
char array[size + 1]; //1 extra space to accommodate `\0` character
printf("%d\n", sizeof(array));
This will print sizeof(char) * (size+1) proving the array creation dynamically.
The only disadvantage of this way over malloc way is after declaring an array (which is of user-input size) you can't change the array size in program. It's fixed.
While using dynamic memory allocation (malloc, calloc) you can change the array size whenever possible in a program by freeing the memory.
Since variable length array is possible in c99 you may have to use gcc --std=c99 -c program.c to compile your source code. For other compiler refer the proper compiler manual.

Storing using malloc() or realloc() and printing data in C [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
Could someone please tell me about what is wrong with the code? Sorry if I'm new at this but I am trying to get this right for a long time. I am trying to get input from the user and then print the values. The following code is just an example.
I try to run the code but I get run-time errors. Can anyone pls help?
#include <stdio.h>
#include <stdlib.h>
typedef struct poly
{
int kill;
float bill;
char katana[50];
} koly;
typedef koly* terma;
int main()
{
int count = 0;
terma ren;
ren = (terma)malloc(sizeof(koly));
ren = (terma)realloc(6*sizeof(koly));
printf("We can store now:\n\n");
while(++count<= 2)
{
scanf("%d",ren->kill);
scanf("%f",ren->bill);
scanf("%s",ren->katana);
}
while(++count<= 2)
{
printf("\n%d\n",ren->kill);
printf("\n%f\n",ren->bill);
printf("\n%s\n",ren->katana);
}
}
About your error:
scanf("%d",ren->kill);
scanf("%f",ren->bill);
These should be pointers, so the corrected version is:
scanf("%d",&ren->kill);
scanf("%f",&ren->bill);
Also, realloc expects 2 arguments unlike malloc. The first should be a pointer to the address you are reallocing, and the second should be the new size. So:
ren = realloc(ren, 6 * sizeof(koly));
I have two other things to say about your code. First: it is unnecessary to cast the return value of malloc in C (and is frowned upon). Also, NEVER use scanf with the "%s" format specifier. This is extremely insecure and can easily lead to crashes and worse. The best method is to use fgets, so scanf("%s",ren->katana); would become this:
fgets(ren->katana, sizeof(ren->katana), stdin);
Edit:
Here is my explanation for why casting the return value of malloc/realloc should be avoided:
It's not really because it's wrong; it's because it is bad practice to do so in C. Since a void* type is automatically converted to any pointer type, the typecasting is superfluous, the code is less readable (IMO), and it makes changes more difficult. For example, take your case:
ren = (terma)malloc(sizeof(koly));
I personally would rewrite this line like so:
ren = malloc(sizeof(*ren));
This allows for easily changing the type of ren. If ren were changed to another data type (such as int* or struct sockaddr_in* or anything else), it would automatically work. You wouldn't need to change the type in the cast or the type in the sizeof(). Both will automatically work for the new type. For arrays, it works the same:
int* myArr = malloc(42 * sizeof(*myArr));
If I instead wanted myArr to hold an array of 42 floats, the change is simple:
float* myArr = malloc(42 * sizeof(*myArr));
Note: In C++, the typecast is required as it doesn't automatically convert void* to other pointer types, but you really shouldn't be using malloc et al in C++ anyways when you have new (plus this is a C question, not C++).
void *realloc(void *ptr, size_t size);
realloc takes two arguments, the prototype is as above, what you have missed in your code is to give the pointer for which you want to reallocate the memory.
you have to use, ren = (terma)realloc( rem, 6*sizeof(koly));
and another error is you have missed & operator in scanf function, it should be, scanf("%d",&ren->kill);
And its not the run time error, did you get the code compiled correctly...?
Realloc() takes two arguments. how does it even compiled?
ren = (terma)realloc(ren,6*sizeof(koly));
You also need scanf corrected:
scanf("%d",&ren->kill);
scanf("%f",&ren->bill);
But just word of caution: You are over-writing your only one object.

Resources