I am learning C and I have tried to build a program that outputs its own source. This is my source:
#include <stdio.h>
int S = 512;
int main(){
FILE * fp;
fp = fopen("hello.c","r");
char * line = (char *) malloc(S);
int i = 0;
while (i == 0)
{
i = feof(fp);
printf("%s",line);
fgets(line,S,fp);
}
fclose(fp);
}
I have used the tcc compiler and I got this output:
But notice, I got a hyphen before #include. The rest of the output is correct.
So please can someone explain why I got this hyphen??
You're printing the first line before you've read anything.
#include <stdio.h>
int main(){
FILE *fp = fopen("hello.c", "r");
char line[256];
while (fgets(line, sizeof line, fp) != NULL)
printf("%s",line);
fclose(fp);
return 0;
}
#ooga gave you the correct answer.
The why is that malloc doesn't initialize the memory before it returns it to you, unlike its sister calloc.
Most likely, on another platform / compiler, you'd get something different.
Some compilers use a debug heap that initializes "unitialized" memory to a specific value. The release mode will probably result in random garbage instead of a '-' everytime.
Related
I am getting a segmentation fault when I want to run this program. It is supposed to by a self-written grep function but case-insensitive. The same code for case-sensitive works just fine so it might have something to do with tolower()?. Please help.
Used VS code in Ubuntu on a Windows PC.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int main (int argc, char *argv[]) {
if (argc > 3) {
printf("Too many arguments. Only use 2: your search string and the file name.");
return -1;
}
//FILE * fp;
FILE * fp = fopen(argv[2], "r");
if(fp == NULL) {
perror("Unable to open file!");
return -1;
}
char * buffer = NULL;
size_t bufsize = 0;
char * lowerBuffer = malloc(sizeof(strlen(buffer)));
for (int i = 0; buffer[i] != '\0'; i++) {
lowerBuffer[i] = tolower(buffer[i]);
}
printf("tolower: %s", lowerBuffer);
while (getline(&buffer, &bufsize, fp) != -1) {
if (strstr(buffer, argv[1]))
{
printf("%s", buffer);
}
//printf("%zd", strlen(buffer));
}
fclose(fp);
free(buffer);
//getline();
return 0;
}
Compiled with gcc mygrepin.c, run with ./a.out test test.txt.
This is what my test.txt looks like:
hallo das ist ein Test.
test
test
test
test
test
I am expecting this output for this command ./a.out test test.txt:
hallo das ist ein Test.
test
test
test
test
test
You try to use
malloc(sizeof(strlen(buffer)))
on an object you just defined as Null
char * buffer = NULL;
Malloc is used to allocate space. What you want to do is to allocate space for the size of a string with the length of your variable buffer. Buffer is null.
Edit: As a comment pointed out not no space is allocated. It is either 4 or 8 depending on your machine. It works on the type. A pointer should return the value of 4 or 8 depending on your architecture of the system. Thanks to #mch for pointing that out. Even though this is true, the problem still remains and was caused by the buffer never being set to a value besides NULL.
So, I'm getting a really weird error in my program, and I've narrowed it down to something to do with getline() and declaring an array of size greater than 8. However, I'm super confused as to why it's doing that, so any help or explanation is greatly appreciated.
#include <stdio.h>
#include <stdlib.h>
void populateConfig();
int main(int arc, char *argv[])
{
// when thing is size 8 it works fine
char thing[9];
populateConfig();
return 0;
}
void populateConfig(){
FILE *fp;
char string1[1000], string2[1000];
char *line;
int len = 0;
fp = fopen("ws.conf", "r");
while(fscanf(fp, "%s", string1) != -1){
// Commenting out if statement prevents crash
if(string1[0] == '#'){
getline(&line, &len, fp);
continue;
}
}
fclose(fp);
}
So I'm just reading in a config file, and as shown, when I change the size of thing to 8 or less, it works, and when I comment out the if statement in populateConfig() it also works. Is this something to do with the stack or memory? Should I do something differently?
You need to initialize char *line to NULL first. Then before returning, free it.
https://linux.die.net/man/3/getline
Am trying to open a file(Myfile.txt) and concatenate each line to a single buffer, but am getting unexpected output. The problem is,my buffer is not getting updated with the last concatenated lines. Any thing missing in my code?
Myfile.txt (The file to open and read)
Good morning line-001:
Good morning line-002:
Good morning line-003:
Good morning line-004:
Good morning line-005:
.
.
.
Mycode.c
#include <stdio.h>
#include <string.h>
int main(int argc, const char * argv[])
{
/* Define a temporary variable */
char Mybuff[100]; // (i dont want to fix this size, any option?)
char *line = NULL;
size_t len=0;
FILE *fp;
fp =fopen("Myfile.txt","r");
if(fp==NULL)
{
printf("the file couldn't exist\n");
return;
}
while (getline(&line, &len, fp) != -1 )
{
//Any function to concatinate the strings, here the "line"
strcat(Mybuff,line);
}
fclose(fp);
printf("Mybuff is: [%s]\n", Mybuff);
return 0;
}
Am expecting my output to be:
Mybuff is: [Good morning line-001:Good morning line-002:Good morning line-003:Good morning line-004:Good morning line-005:]
But, am getting segmentation fault(run time error) and a garbage value. Any think to do? thanks.
Specify MyBuff as a pointer, and use dynamic memory allocation.
#include <stdlib.h> /* for dynamic memory allocation functions */
char *MyBuff = calloc(1,1); /* allocate one character, initialised to zero */
size_t length = 1;
while (getline(&line, &len, fp) != -1 )
{
size_t newlength = length + strlen(line)
char *temp = realloc(MyBuff, newlength);
if (temp == NULL)
{
/* Allocation failed. Have a tantrum or take recovery action */
}
else
{
MyBuff = temp;
length = newlength;
strcat(MyBuff, temp);
}
}
/* Do whatever is needed with MyBuff */
free(MyBuff);
/* Also, don't forget to release memory allocated by getline() */
The above will leave newlines in MyBuff for each line read by getline(). I'll leave removing those as an exercise.
Note: getline() is linux, not standard C. A function like fgets() is available in standard C for reading lines from a file, albeit it doesn't allocate memory like getline() does.
I need to write a code that will print the frequency of each word from a given file. Words like "the" and "The" will count as two different words. I've written some code so far but the command prompt stops working when I try to run the program. I just need some guidance and to be pointed in the best direction for this code, or I would like to be told that this code needs to be abandoned. I'm not very good at this so any help would be very appreciated.
#include <stdio.h>
#include <string.h>
#define FILE_NAME "input.txt"
struct word {
char wordy[2000];
int frequency;
} words;
int word_freq(const char *text, struct word words[]);
int main (void)
{
char *text;
FILE *fp = fopen(FILE_NAME, "r");
fread(text, sizeof(text[0]), sizeof(text) / sizeof(text[0]), fp);
struct word words[2000];
int nword;
int i;
nword = word_freq(text, words);
puts("\nWord frequency:");
for(i = 0; i < nword; i++)
printf(" %s: %d\n", words[i].wordy, words[i].frequency);
return 0;
}
int word_freq(const char *text, struct word words[])
{
char punctuation[] =" .,;:!?'\"";
char *tempstr;
char *pword;
int nword;
int i;
nword = 0;
strcpy(tempstr, text);
while (pword != NULL) {
for(i = 0; i < nword; i++) {
if (strcmp(pword, words[i].wordy) == 0)
break;
}
if (i < nword)
words[i].frequency++;
else {
strcpy(words[nword].wordy, pword);
words[nword].frequency= 1;
nword++;
}
pword = strtok(NULL, punctuation);
}
return nword;
}
First off all:
char *text;
FILE *fp = fopen(FILE_NAME, "r");
fread(text, sizeof(text[0]), sizeof(text) / sizeof(text[0]), fp);
Reads probably 4 bytes of your file because sizeof(text[0]) is 1 and sizeof(text) is probably 4 (depending on pointer size). You need to use ftell() or some other means to get the actual size of your data file in order to read it all into memory.
Next, you are storing this information into a pointer that has no memory allocated to it. text needs to be malloc'd or made to hold memory in some way. This is probably what is causing your program to fail to work, just to start.
There are so so SO many further issues that it will take time to explain them:
How you are using strcpy to blow up memory when you place it intotempstr
How even if that weren't the case, it would copy probably the whole file at once, unless the file had NULL terminated strings within, which it may, so perhaps this is ok.
How you compare nwords[i].wordy, even though it is not initialized and therefore garbage.
How, even if your file were read into memory correctly, you look a pword, which is unitialized for your loop counter.
Please, get some help or ask your teacher about this because this code is seriously broken.
hi i have the following code below, where i try to get all the lines of a file into an array... for example if in file data.txt i have the following:
first line
second line
then in below code i want to get in data array the following:
data[0] = "first line";
data[1] = "second line"
My first question: Currently I am getting "Segmentation fault"... Why?
Exactly i get the following output:
Number of lines is 7475613
Segmentation fault
My second question: Is there any better way to do what i am trying do?
Thanks!!!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char* argv[])
{
FILE *f = fopen("data.txt", "rb");
fseek(f, 0, SEEK_END);
long pos = ftell(f);
fseek(f, 0, SEEK_SET);
char *bytes = malloc(pos);
fread(bytes, pos, 1, f);
int i =0;
int counter = 0;
for(; i<pos; i++)
{
if(*(bytes+i)=='\n') counter++;
}
printf("\nNumber of lines is %d\n", counter);
char* data[counter];
int start=0, end=0;
counter = 0;
int length;
for(i=0; i<pos; i++)
{
if(*(bytes+i)=='\n')
{
end = i;
length =end-start;
data[counter]=(char*)malloc(sizeof(char)*(length));
strncpy(data[counter],
bytes+start,
length);
counter = counter+1;
start = end+1;
}
}
free(bytes);
return 0;
}
First line of the data.txt in this case is not '\n' it is: "23454555 6346346 3463463".
Thanks!
You need to malloc 1 more char for data[counter] for the terminating NUL.
after strncpy, you need to terminate the destination string.
Edit after edit of original question
Number of lines is 7475613
Whooooooaaaaaa, that's a bit too much for your computer!
If the size of a char * is 4, you want to reserve 29902452 bytes (30M) of automatic memory in the allocation of data.
You can allocate that memory dynamically instead:
/* char *data[counter]; */
char **data = malloc(counter * sizeof *data);
/* don't forget to free the memory when you no longer need it */
Edit: second question
My second question: Is there any
better way to do what i am trying do?
Not really; you're doing it right. But maybe you can code without the need to have all that data in memory at the same time.
Read and deal with a single line at a time.
You also need to free(data[counter]); in a loop ... and free(data); before the "you're doing it right" above is correct :)
And you need to check if each of the several malloc() calls succeeded LOL
First of all you need to check if the file got opened correctly or not:
FILE *f = fopen("data.txt", "rb");
if(!f)
{
fprintf(stderr,"Error opening file");
exit (1);
}
If there is error opening the file and you don't check it, you'll get a seg fault when you try to fseek on an invalid file pointer.
Apart from that I see no errors. Tried running the program, by printing the value of the data array at the end, it ran as expected.
One thing to note is that you're opening your file as binary - line termination disciplines may not work as you expect on your platform (UNIX is lf, Windows is cr-lf, some versions of MacOS are cr).