I'm writing a code for homework that uses functions and pointers to read a file and fix the capitalization errors in it.
The goal is to read a pre-written file and fix it, adding line numbers to the beginning of each line. (i.e., tiTle -> 1. Title)
I think I've got the basic logic down, but there must be a bug that I'm not seeing, because it stops responding immediately after I compile and run it.
Here's my main() function.
FILE *casefixer;
casefixer = fopen("casefixer.txt", "r+");
char* ch;
int* char_in_word;
int* line_num;
*char_in_word = 0;
*line_num = 1;
while((fscanf(casefixer, "%c", ch)) != EOF){
fscanf(casefixer, "%c", ch);
fprintf(casefixer, "%d. ", *line_num);
if(fix_caps(ch, char_in_word, line_num))
fprintf(casefixer, "\n");
fix_caps(ch, char_in_word, line_num);
fprintf(casefixer, "%c", *ch);
}
fclose(casefixer);
char* ch; // uninitialized
int* char_in_word; // -||-
int* line_num; // -||-
*char_in_word = 0; // dereferencing uninitialized pointer - undefined behavior
*line_num = 1; // -||-
You don't have to use pointers when you see them in function declaration. If you're sure the function won't store them or try to allocate new memory for them, take an address of a regular variable:
char ch;
fscanf(casefixer, "%c", &ch) // ch is on stack longer than fscanf, everything's OK
By using "%c" you can only read a single character instead of a line. I recommend you use fgets here.
The call of fscanf in the loop should be deleted since you've already called that in the while((fscanf(casefixer, "%c", ch)) != EOF).
Writing while reading is not easy, especially when you want to rewrite what you've read before. You need to reposition your stream position indicator. So I think the better way should be you store your new file into a buffer and then write the buffer into the file.
In this two lines:
if(fix_caps(ch, char_in_word, line_num))
fprintf(casefixer, "\n");
If I understand it right, you should use "continue" in this if statement.
In your code, the variable line_num is always 1. You should do the increment at the end of loop.
Related
Alright, so I am working on linux and emacs for the first time using C, and coming from pretty beginner level java programming in eclipse, my new CS course is really daunting. SO much stuff has been thrown at me as if I already knew it...
Anyway, the current part of my assignment I am working on involves reading in text from a file (doing that by piping a text file as standard input into my program). Currently I had three functions, a main function where I read in the file / call other functions, a function that reverses the order of a single word (apple becomes elppa) with *char beg and *char end as parameters, and a function that reverses the order of every word in a line of words, calling the previous function and taking a char *str as a parameter.
I am having trouble reading in the files in my main method in a way that makes it easy to utilize these functions. Here's a snippet of how I am reading them in currently, but as you can see I haven't figured out a way to store a line of words and send that into my function (I need to reverse line by line, so I can't just add every single char to one long array)
enter code here``
char line[8192]
int location = 0;
FILE *in = stdin;
int buff = 0;
while (buff = fgetc(in))
{
fprintf(stderr, "Character is: %d '%c' \n", buff, (char)buff);
if (buff == EOF)
{
break;
}
line[location] = (char)buff;
location++;
}
line[location] = '\0';
If you want to get a whole line, you can do this:
char line[MAX_LINE_SIZE];
fscanf(in, "%[^\n]", line);
//do whatever you need with the line
fscanf(in, "%[\n]", line);
The first fscanf call reads a whole line and store in variable line.
But it doesn't skip that line! If you use it again, it will store the very same line.
The second fscanf call is for this: it stores '\n' in variable line and skips the line you read previously.
If you want, you can create another buffer to get the '\n' and skip the line:
char garbage[2];
fscanf(in, "%[\n]", garbage);
I hope this helps.
I need to save every line of text file in c in a variable.
Here's my code
int main()
{
char firstname[100];
char lastname[100];
char string_0[256];
char string[256] = "Vanilla Twilight";
char string2[256];
FILE *file;
file = fopen("record.txt","r");
while(fgets(string_0,256,file) != NULL)
{
fgets(string2, 256, file);
printf("%s\n", string2);
if(strcmp(string, string2)==0)
printf("A match has been found");
}
fclose(file);
return 0;
}
Some lines are stored in the variable and printed on the cmd but some are skipped.
What should I do? When I tried sscanf(), all lines were complete but only the first word of each line is printed. I also tried ffscanf() but isn't working too. In fgets(), words per line are complete, but as I've said, some lines are skipped (even the first line).
I'm just a beginner in programming, so I really need help. :(
You're skipping over the check every odd number of lines, as you have two successive fgets() calls and only one strcmp(). Reduce your code to
while(fgets(string_0,256,file) != NULL)
{
if( ! strcmp(string_0, string2) )
printf("A match has been found\n");
}
FWIW, fgets() reads and stores the trailing newline, which can cause problem is string comparison, you need to take care of that, too.
As a note, you should always check the return value of fopen() for success before using the returned pointer.
I'm new to C and stackoverflow, so pardon me if my question is silly or a duplicate.
So i tried to read some lines of string (and integers) from a .txt files and store it into an array of tuples. The strings read from the file seems to contain '\n' everytime, so i use strcspn() to remove it.
FILE* f = fopen("board.txt","r");
int x;
size_t size = 30;
char *buffer;
for (i=1;i<=32;i++)
{
buffer = (char *)malloc(size);
x = getline(&buffer,&size,f);
buffer[strcspn(buffer,"\n")] = 0;
A[i].name = buffer;
buffer = (char *)malloc(size);
x = getline(&buffer,&size,f);
buffer[strcspn(buffer,"\n")] = 0;
A[i].type = buffer;
buffer = (char *)malloc(size);
x = getline(&buffer,&size,f);
A[i].price = atoi(buffer);
}
for (i=1;i<=32;i++)
printf("%s ",A[i].name);
for (i=1;i<=32;i++)
printf("%s ",A[i].type);
However, when i tried the code above, the printf failed to print anything. But then when i tried to use \n in the printf ( printf("%s\n",A[i].type); ) it worked just fine. It seems like the strings completely disappear when i remove the "\n", and then come back only when i put '\n' as i print it.
Can someone explain what is wrong in the code? Or is it a library problem? Thank you in advance.
Edit : So to explain it a little further, i need those string (name and type) to be printed into 'boxes' to form a kind of board game, so i think bringing newline would cause a lot of trouble later on.
This is the correct behavior. The '\n' causes the OS to flush the buffer used for prints, so that it appears on stdout. Without a '\n' the OS isn't forced to write your print to stdout yet.
printf belongs to the Standard I/O library, it is a line buffered function. So when this function is called, it stores characters in a buffer and the only way to get the output (to stdout) is to flush with a newline character. This is the way it was designed so as to maintain a minimal number of system calls as possible.
Try eliminating this,
buffer[strcspn(buffer,"\n")] = 0;
I'm writing a version of the Unix expand utility that replaces tabs with spaces in a file. To do this, I'm reading in each character and testing if it is a tab character. If it is, it replaces the tab with the given amount of spaces, otherwise the character gets printed.
My main method goes like
int main(int argc, char *argv[]){
FILE *fp;
char *help1="-help";
char *help2= "--help";
//int spaces; //number of spaces to replace tabs
fp= fopen(argv[1], "rw");
parse_file(fp, 4);
fclose(fp);
return 0;
}
the parse_file method goes like
void parse_file(FILE *fp, int spaces)
{
int i; //loop counter
char c; //current character
while (c!= EOF)
{
c= getchar(); //get char from stream
if (c=='\t') //if char is a tab
{
for (i=0; i< spaces; i++)
putchar(" "); //replace with spaces
}
else
putchar(c); //otherwise, print the character
}
}
When compiling, I get an integer from pointer without cast warning for putchar(" "); and the program hits a segfault when executing.
So, my questions:
1- What is the warning "makes integer from pointer without cast" all about? What can I do to resolve it?
2- The code generates a segfault on execution with a text file passed in as an argument. Is there anything in this code that would cause that?
you must use
putchar(' ')
instead
putchar(" ")
You're calling putchar on a string (" "), but it wants a char argument (' '). (Actually an int, but only passing a char is safe.)
The segfault is probably due to the fclose on fp, which may be NULL. You should check the return value from fopen. The reason you only notice after parse_file is that it doesn't touch fp at all (it reads from stdin and writes to stdout). To use the stream fp, you should use getc(fp) and putc(fp) instead. (That still won't work because you'd overwrite the stream with more data than you're reading from it, so you'll get garbage out.)
In fact, the program is sure to segfault when no command line argument is given. Either fopen segfaults because it is handed the null pointer argv[1], or it returns a null pointer itself.
When writing these kinds of programs, please adhere to the Unix philosophy and write them as filters: read from stdin, write to stdout. Don't modify a file in-place if you don't have to.
In C string literals are of type char *, a pointer to some area containing string characters.
" " is a string literal, not a character. Use ' ' when you need a single character
As everyone else says, re. The use of char vs. string. As for the logic behind the actual error message you see, the string is a pointer to a const array of characters. Hence the error is saying it is converting the pointer to an int. Most of the char functions work with ints.
To summarise the issues (I'm repeating stuff other people have said, but issues 5 and 6 havehas not been mentioned so far):
putchar() does not take a string pointer as an argument but an int - the constant ' ' is an acceptable parameter
you don't check that argc > 1 before using argv[1]
you don't check that fopen() successfully opens the file
c should be defined as an int since in some character sets (char) -1 (0xFF) is a legitimate character and also the comparison c == EOF may fail if c is not sign extended
The first time through the loop c is used uninitialised and in the loop you also treat EOF as a normal character. The normal idiom in C programs is
int c;
while ((c = fgetc(fp)) != EOF)
{
// do stuff with c
}
You are getting your characters from stdin and not fp hence use fgetc() not getchar()
I think that covers everything.
To answer your explicit question, you get the warning "makes integer from pointer without cast" when an int is expected but you use a pointer (in this case the type of " " is const char*).
In addition to what has already been said, getchar() returns int not char. EOF is an int constant. You will need to read the result from getchar() into an int, check for EOF, and if not found, cast the int into a char.
The Problem was to find and replace a string in a C File.
I am new to C Files. I have tried the following code but I didnt get any output:
#include<stdio.h>
#include<string.h>
int main()
{
FILE *f1,*f2;
char *src,*dest,*s1,ch,ch1,ch2,ch3;
int i;
f1=fopen("input.txt","rw");
f2=fopen("dummy.txt","rw");
src="mor";
dest="even";
while(ch!=EOF)
{
ch=fgetc(f1);
if(ch==src[0]) //Finding 1st char of src
{
fgets(s1,strlen(src),f1);
if(strcmp(src+1,s1)==0) //Finding occurance of "src" in file
{
fseek(f1,strlen(src)-1,SEEK_CUR);
while(ch1!=EOF) //Copying remaining data into another file
{
ch1=fgetc(f1);
fputc(ch1,f2);
}
fseek(f1,-strlen(src),SEEK_CUR);
for(i=0;i<strlen(dest);i++) //replacing "src" with "dest"
{
ch2=dest[i];
fputc(ch2,f1);
}
fclose(f1);
f1=fopen("input.txt","a");
while(ch3!=EOF) //Appending previosly copied data into 1st file
{
ch3=fgetc(f2);
fputc(ch3,f1);
}
}
}
}
fclose(f1);
fclose(f2);
}
The Contents of input.txt is "morning".
Kindly point the ERROR in the logic and also give an efficient code for the same.
Thanks in Advance.
Reading files in C is usually a bit messy. The first problem that I see is the way ch is used in the main loop. The first time
while (ch != EOF)
is executed, ch is uninitialized, and if it happens to hold EOF, the main loop will not execute at all. I usually use the following structure for reading from files:
FILE *fInput = fopen("input.txt", "r");
int ch; /* need an int to hold EOF */
for (;;)
{
ch = fgetc(fInput);
if (ch == EOF) break;
...
}
In addition, you may need to read up on file pointer concept. For example, after reading the remainder of src, you fseek() forward, and skip some more characters before you copy data to f2. Essentially, you read m, read or (with fgets() - and into an unallocated buffer s1 that would go ka-boom on you some time in the near future), skip 2 more characters (now your pointer is at last n of "morning"), copy "ng" into f2, try to write EOF to f2 in this loop (hence the above pattern for reading until EOF), seek two characters back (which may fail once you reach EOF, my C file functions are a bit rusty these days), write "even" to f1 (which should, if I am wrong about seek after EOF, set input file to "mornieven", and not change it if I am correct). In summary, I don't think the code does what you intend it to do.
I would recommend building up your function. Each one of the following can be written as a program that you should test and finish before going to next step:
read the file safely, and print it out
detect the contents of src, and print the rest of input
save the rest of the input to second file instead of printing
replace src with dest in first file, and ignore the rest (since you open input file with 'rw', this will truncate the rest of input). You may need to do an fseek() to clear the EOF status. Also look at ftell() to record a position that you can jump back to using fseek()
finally, copy in everything you have saved to second file after replacing src with dest (no need to close f1 here. But it is better to open f2 as write, close after copy from first file, and reopen as read to perform the copy back to f1).
In addition, when you need a buffer (such as s1), just use a large enough array for now, but look into malloc() and free() functions to perform dynamic memory allocations for situations like these.
One simple way to do the replace would be to first read in the whole file into a buffer
e.g.
FILE* fpIn = fopen("file.txt","rb");
fseek(fpIn, 0L, SEEK_END);
size_t s = ftell(fpIn);
fseek(fpIn, 0L, SEEK_SET);
void* buf = malloc(s);
fread(buf,s,1,fpIn);
now while writing the file, check for your string
char src[] = "mor";
char dest[] = "even";
int lenSrc = strlen(src);
int lenDest = strlen(dest);
for (char* ch = buf; ch < buf + s; ++ch)
{
if ( !memcmp( ch, src, lenSrc ) )
{
fwrite( dest, 1,lenDest, fpOut );
ch += lenSrc;
}
else
{
fputc( *ch, fp );
}
}
disclaimer: haven't compiled this
You are printing the wrong thing in your output. Print, "ch", not the file pointer.
while(ch!=EOF)
{
ch=getc(f1);
printf("%c",ch);
}
while(ch!=EOF)
{
ch=getc(f2);
printf("%c",ch);
}
Also, f2 is closed at the end during your output. You'll have to reopen it (just like you do with f1.)
At first glance, I see that your code to call fgets is wrong. You have not allocated any memory and you are reading a string into an uninitialized pointer. Read into an array or dynamically allocated memory.
Another problem is that you are declaring ch as char. fgetc() returns an int, and for good reason. It is good to be able to return any possible character or EOF, so EOF shouldn't be a character, so ideally fgetc() returns a bigger type than char.
The upshot is that the loop may well never end, since ch can't possibly hold EOF on some standard implementation. Declare it (and ch1 and ch3) as int.