I have a text file in the following format:
Some information here
Some more information here
I want to check to see if the inputted line is blank (line 2 above). I've tried various things but none of them seem to be working, there's obviously something simple that I am missing here.
void myFunc(char* file_path) {
FILE* file;
char buff[BUFFER_SIZE];
file = fopen(file_name, "r");
bool flag = false;
while(fgets(buff, BUFFER_SIZE, file) != NULL) {
if(buff[0] == '\n') {
flag = true;
}
}
}
I've tried strlen(buff) == 0, strcmp(buff, ""), buff[0] == '\0' and many other things but I still can't seem to be getting this to work properly.
It's possible that the second line has more than just the newline character.
You can use a helper function to test that out.
void printDebug(char* line)
{
char* cp = line;
for ( ; *cp != '\0'; ++cp )
{
printf("%d ", (int)(*cp));
}
printf("\n");
}
By examining the integer values of the characters printed, you can tell whether the line has more than one character, and what those characters are.
Related
FILE *fp = fopen("story.txt", "r");
if(fp == NULL){
printf("\nError opening file.\nExiting program.\n");
exit(1);
}
char text[100];
while(fgets(text, 100, fp) != NULL){
printf("%s", text);
}
printf("\n");
fclose(fp);
I'm trying to print the first 100 characters of a text file, including new lines, however when I use the code above it presents some weird behavior. First of all, it only prints the very last line of the text file, which itself is under 100 characters. Also, if I include two print statements in the while loop i.e.
while(fgets(text, 100, fp) != NULL){
printf("%s", text);
printf("%s", text);
}
It prints a lot more than 125 chars of the text file (somewhere in the thousands, it's a big text file), and the contents of said text is a bunch of seemingly random segments from the file in one constant stream, no new lines or anything.
So I guess my question is is there any way to use fgets so that it prints the text in the file, starting from the top, and includes new lines? I eventually have to use this to turn a text file into a character array, so that I can make a new, modified character array based off of that array, which will be printed to a new text file. So if there is a better way to approach that end goal, that would be appreciated.
EDIT: after some discussion in the comments I've realized that the text I am using is just one big block of text with carriage returns and no newlines. I guess at this point my main problem is how to turn this text file with carriage returns into a character array.
If the goal is to read a text file in lines of 100 characters, and to do away with the carriage returns, you can still use fgets() as long as you remember that fgets() will take characters up to and including the next newline, or until one less than the specified number of characters has been read.
The code below reads a line of text, up to BUFFER_SZ-1 characters, increases the memory allocation to hold a new line of text, and copies the line into the allocated space, removing carriage returns and any trailing newlines. Note that the address of the reallocated space is first stored in a temporary pointer. realloc() returns a null pointer in the event of an allocation error, and this step avoids a potential memory leak.
Since the lines are broken at BUFFER_SZ-1 characters, words may be split across lines, and you may want to develop additional logic to handle this. It would be more efficient to reallocate in larger chunks and less frequently, rather than once for every line, as is done here. Also note that it may be useful to open the file in binary mode to more closely parse line endings.
#include <stdio.h>
#include <stdlib.h>
#define BUFFER_SZ 100
int main(void)
{
FILE *fp = fopen("story.txt", "r");
if (fp == NULL) {
fprintf(stderr, "Unable to open file\n");
exit(EXIT_FAILURE);
}
char buffer[BUFFER_SZ];
char (*text)[sizeof buffer] = NULL;
char (*temp)[sizeof buffer] = NULL;
size_t numlines = 0;
while (fgets(buffer, sizeof buffer, fp) != NULL) {
++numlines;
/* Allocate space for next line */
temp = realloc(text, sizeof(*text) * numlines);
if (temp == NULL) {
fprintf(stderr, "Error in realloc()\n");
exit(EXIT_FAILURE);
}
text = temp;
/* Copy buffer to text, removing carriage returns and newlines */
char *c = buffer;
char *line = text[numlines-1];
while (*c != '\n' && *c != '\0') {
if (*c != '\r') {
*line++ = *c;
}
++c;
}
*c = '\0';
}
if (fclose(fp) != 0) {
fprintf(stderr, "Unable to close file\n");
}
for (size_t i = 0; i < numlines; i++) {
printf("%s\n", text[i]);
}
free(text);
return 0;
}
Another option would be to replace the carriage returns with newlines. This may be what OP had in mind. The above program is easily modified to accomplish this. Note that the \n is removed from the printf() statement that displays the results, since newlines are now included in the strings.
...
/* Copy buffer to text, converting carriage returns to newlines */
char *c = buffer;
char *line = text[numlines-1];
while (*c != '\n' && *c != '\0') {
if (*c == '\r') {
*line++ = '\n';
} else {
*line++ = *c;
}
++c;
}
*c = '\0';
}
if (fclose(fp) != 0) {
fprintf(stderr, "Unable to close file\n");
}
for (size_t i = 0; i < numlines; i++) {
printf("%s", text[i]);
}
...
It doesn't copy one line onto the end of another. It simply reuses the buffer you keep passing it. If you want multiple lines stored, copy them to another buffer, and concatenate them. (See: strcat)
So I've tried searching for a solution to this extensively but can only really find posts where the new line or null byte is missing from one of the strings. I'm fairly sure that's not the case here.
I am using the following function to compare a word to a file containing a list of words with one word on each line (dictionary in the function). Here is the code:
int isWord(char * word,char * dictionary){
FILE *fp;
fp = fopen(dictionary,"r");
if(fp == NULL){
printf("error: dictionary cannot be opened\n");
return 0;
}
if(strlen(word)>17){
printf("error: word cannot be >16 characters\n");
return 0;
}
char longWord[18];
strcpy(longWord,word);
strcat(longWord,"\n");
char readValue[50] = "a\n";
while (fgets(readValue,50,fp) != NULL && strcmp(readValue,longWord) != 0){
printf("r:%sw:%s%d\n",readValue,longWord,strcmp(longWord,readValue));//this line is in for debugging
}
if(strcmp(readValue,longWord) == 0){
return 1;
}
else{
return 0;
}
}
The code compiles with no errors and the function reads the dictionary file fine and will print the list of words as they appear in there. The issue I am having is that even when the two strings are identical, strcmp is not returning 0 and so the function will return false for any input.
eg I get:
r:zymoscope
w:zymoscope
-3
Any ideas? I feel like I must be missing something obvious but have been unable to find anything in my searches.
I see you are appending a newline to your test strings to try to deal with the problem of fgets() retaining the line endings. Much better to fix this at source. You can strip all trailing stuff like this, immediately after reading from file.
readValue [ strcspn(readValue, "\r\n") ] = '\0'; // remove trailing newline etc
The string you are reading contains trailing character(s), and hence is not the same as the string you are comparing it against.
Remove the trailing newline (and CR if that is there); then you do not need to add any newline or carriage return to the string being compared:
int isWord(char *word, char *dictionary){
FILE *fp;
fp = fopen(dictionary, "r");
if (fp == NULL){
fprintf(stderr, "error: dictionary cannot be opened\n");
return 0;
}
if (strlen(word) > 16){
fprintf(stderr, "error: word cannot be >16 characters\n");
return 0;
}
char readValue[50];
while (fgets(readValue, 50, fp) != NULL){
char *ep = &readValue[strlen(readValue)-1];
while (*ep == '\n' || *ep == '\r'){
*ep-- = '\0';
}
if (strcmp(readValue, word) == 0){
return 1;
}
}
return 0;
}
I have a question which maybe fairly simple. I have a file input.txt which is:
cat input.txt
testsuite1
test1
summary information of test
FAIL
testsuite2
test1
summary info ya
PASS
I am writing a program just to read each of these strings into variables and do further processing. What is the best way to do it? I am currently doing:
main() {
FILE *fp;
char testsuite[100],testname[100],summary[100],result[100];
fp = fopen("input.txt", "r");
while(1) {
if(fgets(testsuite,99,fp) == NULL)
{
ferror(fp);
break;
}
if(fgets(testname,99,fp) == NULL)
{
ferror(fp);
break;
}
if(fgets(summary,99,fp) == NULL)
{
ferror(fp);
break;
}
if(fgets(result,99,fp) == NULL)
{
ferror(fp);
break;
}
printf("testsuite: %s testname:%s summary:%s result:%s \n",testsuite,testname,summary,result);
}
fclose(fp);
}
Is there a better way to do it? The problem I am currently facing is that, if input.txt contains even one blank line, the blank like is read into a variable. Whats the best way to avoid it?
Thanks!
You should write your own function that skips empty lines (e.g. called getline()) and use it instead of fgets():
char *getline(char *buf, int size, FILE *fp)
{
char *result;
do {
result = fgets(buf, size, fp);
} while( result != NULL && buf[0] == '\n' );
return result;
}
You could now refine that function to also skip lines that consist of blanks only or whatever you need.
You can remove all blank lines of your files before your loop while.
After the open you parse the whole file and remove the blank ;).
But it don't seems like the best way to do it.
Overwise you can check after each fget if your variables are empty, and in this case, fget again.
Hope that will be helpfull.
If you do this, you will not be able to use the strings you read once loop quits, since each loop overwrites each string in the buffer. However, you could store your strings in a struct array:
typedef struct {
testsuite[100];
testname[100];
summary[100];
result[100];
}test;
test test_array[2];
int main(){
int iIndex=0;
FILE* fpPtr=NULL;
fpPtr = fopen("input.txt", "r");
if(fpPtr==NULL){ //<--- it is very important to check if fopen fails
perror("fopen");
}
for(iIndex=0; iIndex<2; iIndex++){ // 2 because it is the number of elements in test_array
if(fgets(test_array[i].testsuite,99,fp) == NULL)
{
ferror(fp);
break;
}
if(fgets(test_array[i].testname,99,fp) == NULL)
{
ferror(fp);
break;
}
if(fgets(test_array[i].summary,99,fp) == NULL)
{
ferror(fp);
break;
}
if(fgets(test_array[i].result,99,fp) == NULL)
{
ferror(fp);
break;
}
}
}
You can detect blank lines by checking for a newline character at position 0:
fgets(cBuffer, sizeof(cBuffer), fpPtr);
//<-- if the file was created on windows, check for '\r' instead, since a new line in windows is \r\n
if(cBuffer[0]=='\n')
{
printf("blank line"\n);
}
My program reads the specific line from the file properly, however it reads the whole file form the line I specify onward. I am trying to print just one line at a time. How can I make it just read the one line?
The code:
int main()
{
int lineNumber = 5;
static const char filename[] = "Text.txt";
FILE *file = fopen(filename, "r");
int count = 0;
if ( file != NULL )
{
char line[256]; /* or other suitable maximum line size */
while (fgets(line, sizeof line, file) != NULL) /* read a line */
{
if (count == lineNumber)
{
printf("%s", line);
//in case of a return first close the file with "fclose(file);"
}
else
{
count++;
}
}
fclose(file);
}
}
After you've found the desired line, just use a break to exit the loop:
if (count == lineNumber)
{
printf("%s", line);
break;
}
if (count == lineNumber)
{
printf("%s", line);
//in case of a return first close the file with "fclose(file);"
count++;
}
increment count when you get the line you specify,otherwise count will not proceed to indicate next line. That is why your code printed all lines once you got the line you specified. Because the line number count wont increase once it becomes equal to linenumber. so add count++.
You can even break the loop since you don't require rest of the lines to be read after you get the specified line.
Here is my code that is doing the printing that gets messed up. The output is fine when you display it to your screen (terminal). Unfortunately when you redirect it to a text file it gets messed up. It displays the null characters (^#) and Enquiry characters (^E). I have to use a for loop like this or my outputs gets messed up. I can't use the %s option or my output won't be in the way I need it.
FILE *input;
char line[80] = {0};
while(fgets(line, 80, input) != NULL)
{
if((int)line[0] == 46)
{
//printf("You have a period \n");
for(i = 31; i < 80; i++)
{
printf("%c", line[i]);
}
//printf(" ------------------------\n");
memset(line, 0, 80);
comment_flag = 1;
}
}
This is what I mean when I say redirect.
gcc *.c
./a.out > text_file
#include <ctype.h>
and try
if (isprint((unsigned char)line[i]) || isspace((unsigned char)line[i]))
printf("%c", line[i]);
The condition in my condition only keeps printable characters (the isprint()) and space characters ('\n', '\t', ...). Other characters ('\0', '\x05', ...) are simply ignored for output. – pmg
its probably silly, but if in your file, you see your null/empty array positions to be displayed with a special character (^#), then all you have to do is to initialize your array with empty spaces, or better with '\0'.
You can do that even one time in the top of your programm, and if it doesn't work, try do that every time in the while loop, after printing the line into the file you want.
while(fgets(line, 80, input) != NULL)
{
//Your code here
for(i=0; i<80; i++)
line[i]='\0';
}
Just remove the "memset" function and try this.
if you just want to replace your output from screen to file, you just have to do this
#include <stdio.h>
int main ( void )
{
int i;
FILE *file = fopen ( "test.txt", "r" );
FILE *out = fopen ( "output.txt", "w");
if ( file != NULL )
{
char line [ 128 ]; /* or other suitable maximum line size */
while ( fgets ( line, sizeof line, file ) != NULL ) /* read a line */
{
if((int)line[0] == 46)
{
//printf("You have a period \n");
for(i = 31; i < 80; i++)
{
fputs(line,out);
}
}
}
fclose ( file );
fclose ( out );
}
return 0;
}
this writes to file properly, without any special characters displayed, and to your screen too, if you replace fputs, with printf, just like your answer in the top. If i got it right, that's what you want.