The best way to print lines from an inputfile without '\n'? [duplicate] - c

This question already has answers here:
Removing trailing newline character from fgets() input
(14 answers)
Closed 7 years ago.
The task is write a c program to print lines read from an input file (maybe very very large), but without '\n'. Please see the comment in the code below, is it a typical way or good way to do so??
int main() {
const char *input_wavlist_file = "/home/legend0011/Downloads/test-sample-list.txt";
const int BUFFER_SIZE = 100;
FILE *fr = fopen(input_wavlist_file, "r");
if (fr == NULL) {
printf("Error opening input wav list file!\n");
exit(1);
}
char str[BUFFER_SIZE];
while((fgets(str, BUFFER_SIZE, fr)) != NULL) {
char *pch = strchr(str, '\n');
char *filepath = str;
if (pch != NULL) *pch = '\0'; // is this a typical way????????
printf("reading==>%s",filepath);
}
fclose(fr);
}

fgets() comes with a newline character suppress the newline and print it.
size_t n = strlen(str);
if(n>0 && str[n-1] == '\n')
{
str[n-1] = '\0';
}
printf("%s",str);

The issue you're facing here is with fgets() behaviour. As per the man page,
fgets() reads in at most one less than size characters from stream and stores them into the buffer pointed to by s. Reading stops after an EOF or a newline. If a newline is read, it is stored into the buffer....
So, it reads and stores the tralining newline into the read buffer. That is the one which is getting printed to the output. Instead of trying n_not to print_ the newline, you can simply replace the trailing \n with \0 after taking the input to get your issue solved.
As this is a simple replacement operation, without having strchr() also you can get the job done in an easy way.
Simple Algo:
Read the line using fgets().
If the return is not NULL, calculate the length of the input using strlen().
Replace the buffer[strlen-1] element (actually \n, you can double-check) with null \0.
note: The proper signature of main() is int main(void)

This answers the question in your comment. There is no string assign operator in c. You have to provide some space for this new string or destructively ammendment the original.
The simplest way to achieve what you want would be use strncpy to copy the first n characters of your source string to a new destination.

Related

Finding input substring in string extracted from File [duplicate]

This question already has answers here:
strstr not functioning
(2 answers)
Closed 7 years ago.
Basically, I would like to know why this code doesn´t work. It appears that the value of strstr() is always NULL, as all this code ever does is "word not found".
I have already tried if (strstr(retezec,substring)!=NULL), but it doesn't work either.
int main()
{
FILE *files;
files = fopen("Knihovna.txt","rb+");
int i = 0;
while(fgetc(files)!=EOF){
i++;
}
//printf("%d",i);
rewind(files);
char *retezec;
retezec = (char *)malloc(i);
fread(retezec, i, 1, files);
puts("zadejte hledane slovo");
char *substring;
substring = (char *)malloc(50);
fflush(stdin);
fgets(substring,49, stdin);
char *found;
found = strstr(retezec,substring);
if(found){
printf("word found!");
}
else{
puts("word not found");
}
}
It's most likely the result of fgets() reading the trailing newline.
fgets(substring,49, stdin);
This would read the trailing newline if substring has space. So if you input "name". You actually have "name\n".
Remove the trailing newline with:
char *p = strchr(substring, '\n');
if (p) *p = 0; // remove the newline, if present
You have another problem. fread()doesn't NUL terminate. It simply reads the requested bytes. So you would need to check if fread() read i bytes or less and use that number (return value of fread()) to find the actual bytes read. Because it may be less than requested. And then, allocate one extra byte and NUL terminate it if you want to use it as a C-string.

Why does opendir() work for one string but not another?

I would like to open a directory using opendir but am seeing something unexpected. opendir works for the string returned from getcwd but not the string from my helper function read_cwd, even though the strings appear to be equal.
If I print the strings, both print /Users/gwg/x, which is the current working directory.
Here is my code:
char real_cwd[255];
getcwd(real_cwd, sizeof(real_cwd));
/* This reads a virtual working directory from a file */
char virt_cwd[255];
read_cwd(virt_cwd);
/* This prints "1" */
printf("%d\n", strcmp(real_cwd, virt_cwd) != 0);
/* This works for real_cwd but not virt_cwd */
DIR *d = opendir(/* real_cwd | virt_cwd */);
Here is the code for read_cwd:
char *read_cwd(char *cwd_buff)
{
FILE *f = fopen(X_PATH_FILE, "r");
fgets(cwd_buff, 80, f);
printf("Read cwd %s\n", cwd_buff);
fclose(f);
return cwd_buff;
}
The function fgets includes the final newline in the buffer — so the second string is actually "/Users/gwg/x\n".
The simplest (but not necessarily the cleanest) way to solve this issue is to overwrite the newline with a '\0': add the following at the end of the function read_cwd:
n = strlen(cwd_buff);
if(n > 0 && cwd_buff[n - 1] == '\n')
cwd_buff[n - 1] = '\0';
fgets() includes the newline.
Parsing stops if end-of-file occurs or a newline character is found, in which case str will contain that newline character. — http://en.cppreference.com/w/c/io/fgets
You should trim the white space on both ends of the string when reading input like this.
From the fgets man page:
fgets() reads in at most one less than size characters from stream and
stores them into the buffer pointed to by s. Reading stops after an
EOF or a newline. If a newline is read, it is stored into the buffer.
A terminating null byte (aq\0aq) is stored after the last character in
the buffer.
You need to remove the newline character from the string you are reading in.

How to discard the rest of a line in C

I'm trying to write a function that removes the rest of a line in C. I'm passing in a char array and a file pointer (which the char array was read from). The array is only supposed to have 80 chars in it, and if there isn't a newline in the array, read (and discard) characters in the file until you reach it (newline). Here's what I have so far, but it doesn't seem to be working, and I'm not sure what I'm doing wrong. Any help would be greatly appreciated! Here's the given information about what the function should do:
discardRest - if the fgets didn't read a newline than an entire line hasn't been read. This function takes as input the most recently read line and the pointer to the file being read. discardRest looks for the newline character in the input line. If newline character is not in the line, the function reads (and discards) characters from the file until the newline is read. This will cause the file pointer to be positioned to the beginning of the next line in the input file.
And here's the code:
void discardRest(char line[], FILE* file)
{
bool newlineFound = FALSE;
int i;
for(i = 0; i < sizeof(line); i++)
{
if(line[i] == '\n') newlineFound = TRUE;
}
if(!newlineFound)
{
int c = getc(file);
while(c != '\n')
{
c = getc(file);
}
}
}
Your way is much too difficult, besides sizeof always giving the size of its operand, which is a pointer and not the array it points to which you think it is.
fgets has thefollowing contract:
return NULL: Some kind of error, do not use the buffer, its content might be indeterminate.
otherwise the buffer contains a 0-terminated string, with the last non-0 being the retained '\n' if the buffer and the file were both large enough.
Thus, this should work:
So, use strlen() to get the buffer length.
Determine if a whole line was read (length && [length-1] == '\n').
As appropriate:
remove the newline character and return.
discard the rest of the line like you tried.

strcmp not working for fgets file read input string [duplicate]

This question already has answers here:
strcmp on a line read with fgets
(6 answers)
Closed 3 years ago.
I am reading words from file & need to search some specific words, below is my code
string read = malloc(50 * sizeof(char));
FILE* p = fopen("word","r");
while(fgets(read,50,p))
{
printf("%s\n",read);
if(strcmp(read,"apple") == 0)
{
printf("apple found\n");
break;
}
}
And sample file 'word' is as below,
$: more word
liol
apple
scizzors
big
bang
mentalist
scapegrace
goat
goti
Why is strcmp not working in this case, printf can print string read, so char pointer is working fine.
The fgets() function, in most circumstances, retains the newline at the end of the line. Hence yourtext\n will not compare equal to yourtext. You would have noted this with one of my favorite tricks for checking strings:
printf ("[%s]\n", read);
The presence of a newline before the closing ] would have immediately alerted you to the problem, or at a minimum raised an eyebrow.
If you want to strip a newline off before comparing, you can do something like:
int ln = strlen (read);
if ((ln > 0) && (read[ln-1] == '\n'))
read[ln-1] = '\0';
Alternatively, you could skip that and just do:
if (strcmp (read,"apple\n") == 0)
It's not necessarily elegant but, if you don't need to use the word for anything other than that comparison, it'll be just fine.
However, you may then need to worry about the last line in the file in case it has no newline at the end of it so maybe it's better to use the newline-removing code above.
To search for a specific string in the line, rather than match the entire line, strncmp (which searches for n characters) can be used.
if (strncmp(read,"apple",strlen("apple")) == 0)
{
printf("apple found\n");
break;
}

Why fgets is not inputting first value?

I am writing a program to write my html files rapidly. And when I came to write the content of my page I got a problem.
#include<stdio.h>
int main()
{
int track;
int question_no;
printf("\nHow many questions?\t");
scanf("%d",&question_no);
char question[question_no][100];
for(track=1;track<=question_no;track++)
{
printf("\n<div class=\"question\">%d. ",track);
printf("\nQuestion number %d.\t",track);
fgets(question[track-1],sizeof(question[track-1]),stdin);
printf("\n\n\tQ%d. %s </div>",track,question[track-1]);
}
}
In this program I am writing some questions and their answers (in html file). When I test run this program I input the value of question_no to 3. But when I enter my first question it doesn't go in question[0] and consequently the first question doesn't output. The rest of the questions input without issue.
I searched some questions on stackoverflow and found that fgets() looks for last \0 character and that \0 stops it.
I also found that I should use buffer to input well through fgets() so I used: setvbuf and setbuf but that also didn't work (I may have coded that wrong). I also used fflush(stdin) after my first and last (as well) scanf statement to remove any \0 character from stdin but that also didn't work.
Is there any way to accept the first input by fgets()?
I am using stdin and stdout for now. I am not accessing, reading or writing any file.
Use fgets for the first prompt too. You should also malloc your array as you don't know how long it is going to be at compile time.
#include <stdlib.h>
#include <stdio.h>
#define BUFSIZE 8
int main()
{
int track, i;
int question_no;
char buffer[BUFSIZE], **question;
printf("\nHow many questions?\t");
fgets(buffer, BUFSIZE, stdin);
question_no = strtol(buffer, NULL, 10);
question = malloc(question_no * sizeof (char*));
if (question == NULL) {
return EXIT_FAILURE;
}
for (i = 0; i < question_no; ++i) {
question[i] = malloc(100 * sizeof (char));
if (question[i] == NULL) {
return EXIT_FAILURE;
}
}
for(track=1;track<=question_no;track++)
{
printf("\n<div class=\"question\">%d. ",track);
printf("\nQuestion number %d.\t",track);
fgets(question[track-1],100,stdin);
printf("\n\n\tQ%d. %s </div>",track,question[track-1]);
}
for (i = 0; i < question_no; ++i) free(question[i]);
free(question);
return EXIT_SUCCESS;
}
2D arrays in C
A 2D array of type can be represented by an array of pointers to type, or equivalently type** (pointer to pointer to type). This requires two steps.
Using char **question as an exemplar:
The first step is to allocate an array of char*. malloc returns a pointer to the start of the memory it has allocated, or NULL if it has failed. So check whether question is NULL.
Second is to make each of these char* point to their own array of char. So the for loop allocates an array the size of 100 chars to each element of question. Again, each of these mallocs could return NULL so you should check for that.
Every malloc deserves a free so you should perform the process in reverse when you have finished using the memory you have allocated.
malloc reference
strtol
long int strtol(const char *str, char **endptr, int base);
strtol returns a long int (which in the code above is casted to an int). It splits str into three parts:
Any white-space preceding the numerical content of the string
The part it recognises as numerical, which it will try to convert
The rest of the string
If endptr is not NULL, it will point to the 3rd part, so you know where strtol finished. You could use it like this:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char * endptr = NULL, *str = " 123some more stuff";
int number = strtol(str, &endptr, 10);
printf("number interpreted as %d\n"
"rest of string: %s\n", number, endptr);
return EXIT_SUCCESS;
}
output:
number interpreted as 123
rest of string: some more stuff
strtol reference
This is because the previous newline character left in the input stream by scanf(). Note that fgets() stops if it encounters a newline too.
fgets() reads in at most one less than size characters from stream and
stores them into the buffer pointed to by s. Reading stops after an
EOF or a newline. If a newline is read, it is stored into the
buffer
Don't mix fgets() and scanf(). A trivial solution is to use getchar() right after scanf() in order to consume the newline left in the input stream by scanf().
As per the documentation,
The fgets() function shall read bytes from stream into the array
pointed to by s, until n-1 bytes are read, or a < newline > is read and
transferred to s, or an end-of-file condition is encountered
In case of scanf("%d",&question_no); a newline is left in the buffer and that is read by
fgets(question[track-1],sizeof(question[track-1]),stdin);
and it exits.
In order to flush the buffer you should do,
while((c = getchar()) != '\n' && c != EOF)
/* discard */ ;
to clear the extra characters in the buffer

Resources