Use of getdelim - c

#include <stdio.h>
#include <stdlib.h>
main() {
FILE *fp;
char *lineptr = NULL;
size_t len;
size_t read;
fp = fopen("test.txt", "r");
if(NULL == fp) {
exit(1);
}
while((read = getdelim(&lineptr, &len, 33, fp)) != -1) {
printf("%s", lineptr);
}
free(lineptr);
}
In test.txt I have written:
before giving tab !after tab has been given
I have set ! as the delimiter but I don't see any difference between getline and getdelim in getdelim I can set the delimter but in case of getline it is newline character, I want the o/p to be:
before giving tab
after tab has been given
! should be taken as delimiter. How can I do this using getdelim?

This is not tested, but try to change your printf line, so you can see the difference:
printf("%s\n",lineptr);

It's doing exactly what you think it is, it's just that the first string it prints is
before giving tab !
with no new line, followed by after tab has been given
change your print to
printf("%s\n",lineptr);

It's working perfectly fine (and delimiting on '!' as you requested); the only problem is that you are printing out the individual strings exactly as they come in, in a while loop.
Remember: getdelim includes the delimiter in the string (it won't remove the '!' for you).
For the given test case, the first time around the loop will give the string "before giving tab !", and the second time around the loop will give the string "after tab has been given". You are printing them both out without any newlines or anything, so your output looks just the same as the input. I suggest you print a newline after each string, but that won't get rid of the '!'. So you may want to change your print code to:
while((read=getdelim(&lineptr,&len,33,fp))!= -1)
{
if (lineptr[strlen(lineptr)-1] == '!')
lineptr[strlen(lineptr)-1] = '\0';
printf("%s\n",lineptr);
}

char before[256], after[256];
fscanf(fp, "%255[^!]!%255[^\n]", before, after);
printf("%s\n%s", before, after);

See man getdelim. The delim is included in the string, followed by a null character. If you want to print a string followed by an EOL, puts is the fastest way.
puts(lineptr);
If you also want to remove the delim '!', add this before the puts.
lineptr[read - 1] = 0;

Related

Stucking about strcpy at C

I Couldn't understand this code i've left comment line about strcopy. Can you explain it to me? Thanks already. I'm new at c and trying to improve myself. Sometimes i stuck at somewhere and in this situation i couldn't find any solution.
#include <stdio.h>
#include <string.h>
#define SIZE 1000
int main(){
int lwd,cnt;
char read1[SIZE];
char true;
FILE *r = fopen("test.txt","r");
if(r==NULL){
printf("Er.");
}
FILE *cpy =fopen("temp","w");
if(cpy==NULL){
printf("Er.");
fclose(r);
}
printf("Please enter whic line you wanna remove:");
scanf("%d",&lwd);
while(!feof(r)){
strcpy(read1,"\0"); // what does it mean?
fgets(read1,SIZE,r);
if(!feof(r)){
cnt++;
if(cnt != lwd){
fprintf(cpy,"%s",read1);
}
}
}
fclose(r);
fclose(cpy);
remove("test.txt");
rename("temp","test.txt");
FILE *read;
read = fopen("test.txt","r");
if(read == NULL){
printf("Error.");
fclose(read);
}
true=fgetc(read);
while(true != EOF){
printf("%c",true);
true=fgetc(read);
}
getch();
return 0;
}
The statement
strcpy(read1,"\0");
is just copying an empty string to initialize read1.
It's a silly way to do it; read1[0] = 0; is just as good, but as #chux points out in the comments, initializing read1 isn't necessary, and there are other things wrong with the code (e.g., checking result of fgets).
You can see the documentation for the strcpy below.
https://i.stack.imgur.com/AN38r.png
You can see the strcpy copies the second string argument in the first string argument. The first argument is the destination where the string is copied. The second argument is the source from which the complete string is copied.
Therefore we can say that the strcpy line is just to ensure that read1 is always empty before the reading the next line.
If we skip this line then a case where the length of the previously read line is more than the current line can give errors.
It is almost a redundant step here as fgets replaces the '\n' with '\0'. Thus, characters after that do not matter.

How to read a text file into matrix form in C

Given the following text file with the following content in it
SpotA B C
SpotB pass D
Spotc A E F
How to do I break up the words into tokens and store them in a 10 x 10 matrix.
Note that if the content in the file is a matrix size with smaller than 10 x 10, I want to add the character ~ to those positions.
So far this is my code:
char *matrix[10][10];
int loadFileToMatrix(char *filename){
FILE *fp;
int row = 0;
int col= 0;
char *tokens;
char buffer[1000];
fp = fopen(filename,"r");
if(fp == NULL){
perror(filename);
return(1);
}
while((fgets(buffer, sizeof(buffer), fp))!= NULL) {
tokens = strtok(buffer," ");
map[row++][col++] = tokens;
}
return(0);
}
If some can help me figure out how to achieve my goal that would be nice. Currently, I am really confused on how to proceed.
Just use fscanf to read tokens from file to buffer, then copy tokens into your the matrix map. You can use fgetc to detect if it reaches the end of line and the end of file.
char ch;
while (1) {
fscanf(fp, "%s", buffer);
matrix[row][col] = (char *)malloc(sizeof(char) * (strlen(buffer) + 1));
strcpy(matrix[row][col], buffer);
ch = fgetc(fp);
if (ch == ' ') {
col += 1;
}
else if (ch == '\n') {
row += 1;
col = 0;
}
else if (ch == EOF) {
break; // end of file.
}
}
strtok() is a weird function.
The key part of the man page is this:
"On the first call to strtok() the string to be parsed should be specified in str. In each subsequent call that should parse the same string, str should be NULL."
The reason for this is that strtok() alters the string you pass it. It searches through a string until it finds the next character that matches one of the delimiters, and then replaces that delimiter with a null terminator. If the delimiter is found at position n, internally, strtok() saves the position n+1 as the start of the rest of the string.
By calling strtok a second time with a non-null value, you are telling the function to start all over again at the start of that string, and try again to find a delimiter -- which it can never do, because it already found the first one. Instead, your second call to strtok() should pass NULL as the first argument, so each pass can bring out the next token.
If for some reason you need to call strtok() on multiple strings simultaneously, you will overwrite the internally-saved address; only the most recent call is saved properly. The reentrant function strtok_r() is useful in that situation.
If you're ever not sure how to use a function, the man pages are the best resource. You can type man strtok at the command line, or even just google it.
It looks like, in this case, you're using strtok() only once. This will just return the address of the first piece of the buffer, delimited by your delimiters. You need to call strtok() in a loop to get each piece in turn.

How to save every line in file (IN C) in a variable? :)

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.

fscanf() how to go in the next line?

So I have a wall of text in a file and I need to recognize some words that are between the $ sign and call them as numbers then print the modified text in another file along with what the numbers correspond to.
Also lines are not defined and columns should be max 80 characters.
Ex:
I $like$ cats.
I [1] cats.
[1] --> like
That's what I did:
#include <stdio.h>
#include <stdlib.h>
#define N 80
#define MAX 9999
int main()
{
FILE *fp;
int i=0,count=0;
char matr[MAX][N];
if((fp = fopen("text.txt","r")) == NULL){
printf("Error.");
exit(EXIT_FAILURE);
}
while((fscanf(fp,"%s",matr[i])) != EOF){
printf("%s ",matr[i]);
if(matr[i] == '\0')
printf("\n");
//I was thinking maybe to find two $ but Idk how to replace the entire word
/*
if(matr[i] == '$')
count++;
if(count == 2){
...code...
}
*/
i++;
}
fclose(fp);
return 0;
}
My problem is that fscanf doesn't recognize '\0' so it doesn't go in the next line when I print the array..also I don't know how to replace $word$ with a number.
Not only will fscanf("%s") read one whitespace-delimited string at a time, it will also eat all whitespace between those strings, including line terminators. If you want to reproduce the input whitespace in the output, as your example suggests you do, then you need a different approach.
Also lines are not defined and columns should be max 80 characters.
I take that to mean the number of lines is not known in advance, and that it is acceptable to assume that no line will contain more than 80 characters (not counting any line terminator).
When you say
My problem is that fscanf doesn't recognize '\0' so it doesn't go in the next line when I print the array
I suppose you're talking about this code:
char matr[MAX][N];
/* ... */
if(matr[i] == '\0')
Given that declaration for matr, the given condition will always evaluate to false, regardless of any other consideration. fscanf() does not factor in at all. The type of matr[i] is char[N], an array of N elements of type char. That evaluates to a pointer to the first element of the array, which pointer will never be NULL. It looks like you're trying to determine when to write a newline, but nothing remotely resembling this approach can do that.
I suggest you start by taking #Barmar's advice to read line-by-line via fgets(). That might look like so:
char line[N+2]; /* N + 2 leaves space for both newline and string terminator */
if (fgets(line, sizeof(line), fp) != NULL) {
/* one line read; handle it ... */
} else {
/* handle end-of-file or I/O error */
}
Then for each line you read, parse out the "$word$" tokens by whatever means you like, and output the needed results (everything but the $-delimited tokens verbatim; the bracket substitution number for each token). Of course, you'll need to memorialize the substitution tokens for later output. Remember to make copies of those, as the buffer will be overwritten on each read (if done as I suggest above).
fscanf() does recognize '\0', under select circumstances, but that is not the issue here.
Code needs to detect '\n'. fscanf(fp,"%s"... will not do that. The first thing "%s" directs is to consume (and not save) any leading white-space including '\n'. Read a line of text with fgets().
Simple read 1 line at a time. Then march down the buffer looking for words.
Following uses "%n" to track how far in the buffer scanning stopped.
// more room for \n \0
#define BUF_SIZE (N + 1 + 1)
char buffer[BUF_SIZE];
while (fgets(buffer, sizeof buffer, stdin) != NULL) {
char *p = buffer;
char word[sizeof buffer];
int n;
while (sscanf(p, "%s%n", word, &n) == 1) {
// do something with word
if (strcmp(word, "$zero$") == 0) fputs("0", stdout);
else if (strcmp(word, "$one$") == 0) fputs("1", stdout);
else fputs(word, stdout);
fputc(' ', stdout);
p += n;
}
fputc('\n', stdout);
}
Use fread() to read the file contents to a char[] buffer. Then iterate through this buffer and whenever you find a $ you perform a strncmp to detect with which value to replace it (keep in mind, that there is a 2nd $ at the end of the word). To replace $word$ with a number you need to either shrink or extend the buffer at the position of the word - this depends on the string size of the number in ascii format (look solutions up on google, normally you should be able to use memmove). Then you can write the number to the cave, that arose from extending the buffer (just overwrite the $word$ aswell).
Then write the buffer to the file, overwriting all its previous contents.

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

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.

Resources