How to read line by line using system call in C - c

In my program, I can currently read char by char a file with given name "fichier1.txt", but what I'm looking for is to store a line(line char pointer here) and then display it that way :
-ligne 1 : content line 1
-line 2 : content line 2
-ect...
I've tried to store char by char but since it's a pointer and I'm yet that much familiar with pointers I'm not able to store a line and then reuse the pointer to store the char of the next line.
I have to say that it's part of a school projet and I have to use POSIX standard.
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
#include <pthread.h>
#include<string.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(){
int read_fd, write_fd;
off_t offset = 0;
char lu;
struct stat statFd;
char *fichier = "fichier1.txt";
read_fd = open(fichier,O_RDONLY);
stat(fichier, &statFd);
if(read_fd == -1){
perror("open");
exit(EXIT_FAILURE);
}
int i = 0;
char * line; // variable to store line
while(lseek(read_fd,offset, SEEK_SET) < statFd.st_size)
{
if(read(read_fd, &lu, 1) != -1)
{
printf("%c",lu);
offset++;
} else {
perror("READ\n");
close(read_fd);
close(write_fd);
exit(EXIT_FAILURE);
}
}
return 0;
}
I'd like to use open() function and not fopen()

Since you are able to read character after character from the file, the logic in while loop will be used to store an entire line (up to 199 characters, you can increase it though) at once in an array & then display it:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main(void)
{
FILE *fptr=fopen( "fichier1.txt","r");
int i;
char arr[200]; //THIS ARRAY WILL HOLD THE CONTENTS OF A LINE TEMPORARILY UNTIL IT IS PRINTED
int temp_index=0,line_number=1;;
memset(arr,'\0',sizeof(arr));
while((i=getc(fptr))!=EOF)
{
if(i!='\n')
{
arr[temp_index++]=i;
}
if(i=='\n')
{
printf(line %d: %s\n",line_number++,arr);
temp_index=0;
memset(arr,'\0',sizeof(arr));
}
}
return 0;
}

Calling lseek at every iteration may be inefficient and may fail on devices which are incapable of seeking. I would write a program along these lines below if I don't need to store lines.
#include <stdio.h>
#include <stdlib.h>
int main (void)
{
int lc = 0; /* line count */
int c; /* character read */
FILE *fp = fopen("fichier1.txt", "r");
if (fp == NULL) {
perror("fopen");
return EXIT_FAILURE;
}
while ((c = fgetc(fp)) != EOF) {
printf("line %d: ", ++lc);
while (c != '\n' && c != EOF) {
putchar(c);
c = fgetc(fp);
}
putchar('\n');
}
return 0;
}
Or, a program using fgets to read a line at once:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
int main (void)
{
int lc = 0; /* line count */
char buf[4096]; /* buffer to store the line read */
bool newline = true;
FILE *fp = fopen("fichier1.txt", "r");
if (fp == NULL) {
perror("fopen");
return EXIT_FAILURE;
}
while (fgets(buf, sizeof buf, fp) != NULL) {
if (newline)
printf("line %d: ", ++lc);
printf("%s", buf);
newline = strchr(buf, '\n');
}
return 0;
}

Related

How would I create an array of char* after reading an unknown number of strings (each of unknown length) from a file? [duplicate]

This question already has answers here:
How should character arrays be used as strings?
(4 answers)
Closed 12 months ago.
I have a file with an unknown number of strings and each of these strings is of an unknown length.
I would like to make each line of the file its own string in an array of strings.
I tried to use dynamic allocation in a char** array, but I don't think I'm approaching this correctly.
Below is the code I have tried. It's getting stuck in an infinite loop, and I can't figure out why.
(The text file I'm reading from ends with a line break, by the way.)
#include <getopt.h> //for getopts
#include <sys/stat.h> //to do file stat
#include <dirent.h>
#include <string.h>
#include <pwd.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h> //user macros
#include <stdlib.h>
#include <stdbool.h>
#include <libgen.h>
#include <errno.h>
int main(int argc, char *argv[]) {
//storing the filename inside string
char* filename = argv[1];
FILE *fp1 = fopen(filename, "r");
if (fp1 == NULL) {
fprintf(stderr, "Error: Cannot open '%s'. No such file or directory.\n", filename);
return EXIT_FAILURE;
}
/**
* we begin by getting the number of numbers in the file
* the number of numbers = number of lines = number of line breaks
*/
size_t numNumbers = 0;
// while((fscanf(fp1, "%*[^\n]"), fscanf(fp1, "%*c")) != EOF){
// numNumbers = numNumbers + 1;
// }
char c;
while((c = fgetc(fp1)) != EOF){
if(c == '\n'){
numNumbers++;
}
}
fclose(fp1);
FILE *fp2 = fopen(filename, "r");
char** arrayOfStrings = malloc(numNumbers * sizeof(char*));
for(int i = 0; i < numNumbers; i++) {
int len = 0;
if(((c = fgetc(fp1)) != '\n') && (c != EOF)){
len++;
}
arrayOfStrings[i] = malloc(len * sizeof(char));
}
printf("hello1\n");
//for(int i = 0; i < numNumbers; i++){
// fscanf(fp2, "%s", (arrayOfStrings[i]));
//}
fclose(fp2);
// for(int i = 0; i < numNumbers; i++){
// fprintf(stdout, "%s", arrayOfStrings[i]);
// }
return 0;
}
(I'm very new to C, so please go easy on me!)
In C, strings are terminated with a '0' byte, so it looks like your malloc for each string is 1 character too short -- you've only allowed space for the text.
In addition, you mean the count for the size of each line to be a while loop, not an if statement - right now you are counting each line as length "1".
Finally, you are reading off the end of the file in your commented out fscanf code because you haven't closed and reopened it.
Assuming you want to split the input to the strings by the newline character, would you please try:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
char *filename; // filename to read
char **arrayOfStrings = NULL; // array of strings
char line[BUFSIZ]; // line buffer while reading
char *p; // temporal pointer to the input line
int i, num; // counter for lines
FILE *fp; // file pointer to read
if (argc != 2) {
fprintf(stderr, "usage: %s file.txt\n", argv[0]);
return EXIT_FAILURE;
}
filename = argv[1];
if (NULL == (fp = fopen(filename, "r"))) {
perror(filename);
return EXIT_FAILURE;
}
// read the input file line by line
while (fgets(line, BUFSIZ, fp)) {
if ((p = strrchr(line, '\n'))) *p = '\0'; // remove trailing newline, if any
if ((p = strrchr(line, '\r'))) *p = '\0'; // remove trailing cr character, if any
if (NULL == (arrayOfStrings = realloc(arrayOfStrings, (num + 1) * sizeof(char **)))) {
// enlarge the array according to the line count
perror("realloc");
return EXIT_FAILURE;
}
if (NULL == (arrayOfStrings[num] = malloc(strlen(line) + 1))) {
// memory for the string of the line
perror("malloc");
return EXIT_FAILURE;
}
strcpy(arrayOfStrings[num], line);
num++;
}
// print the strings in the array
for (i = 0; i < num; i++) {
printf("%d %s\n", i, arrayOfStrings[i]);
}
fclose(fp);
return 0;
}
If the input file looks something like:
This
is
the
input.
Then the output will be:
0 This
1 is
2 the
3 input.

Something weird using fgets

If I'm printing the whole string everything looks good, whitespace and indenting looks perfect (I'm loading the source file with this code).
But if I'm trying to print a single character in the buffer I'm getting letters where there are not supposed to be any.
For example, if I print buffer[2] I'm getting letters where it should be whitespace, but if I print the whole string the letters aren't there.
Here is my code that's not working:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void) {
char *buffer = (char*) malloc(100*sizeof(char));
FILE *myFile;
myFile = fopen("thisSourceFile.c", "r");
if (!myFile) {
printf("could not open file");
}
else {
while(fgets(buffer,100,myFile)) {
printf("%c \n",buffer[2]);
}
}
fclose(myFile);
free(buffer);
buffer = NULL;
return 0;
}
OUTPUT:
n
n
n
t
h
I
y
f
p
l
w
p
}
r
u
e
As you can se it is printing letters where it should by whitespace. Those letters are not there if I print the whole string.
If you're interested in parsing a source file and processing each character, this might be a solution.
But there are two constants; charsand num_lines_to_read.
M.M mentions in the comments below that isprint() isn't fully portable and comes with some quirks to be careful of.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(void) {
const int chars = 100; /* Num chars per line to read */
const int num_lines_to_read = 3; /* Num lines to read */
char *buffer = (char*) malloc(chars*sizeof(char));
int i = 0, j = 0;
FILE *myFile;
myFile = fopen("thisSourceFile.c", "r");
if (myFile == NULL) {
printf("could not open file");
fclose(myFile);
return 1;
}
for(i=0; i<num_lines_to_read; i++)
{
if(fgets(buffer,chars,myFile) != NULL)
{
while(isprint((unsigned char) buffer[j]))
{
printf("%c", (buffer[j]));
j++;
}
j=0;
}
}
fclose(myFile);
free(buffer);
return 0;
}
Example output (itself!):
#include <stdio.h>#include <stdlib.h>#include <ctype.h>

Why this piece of code don't work? (C Basic IO)

I recently write a piece of code that count the number of lines in a text file, however, something the while loop part just don't work properly and loop forever. Anyone can help me to find out what is the problem with that piece of code?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
FILE *fp;
int main() {
fp=fopen("C:\\Users\\Alan\\Desktop\\text.txt","r");
int i=0;
while(!feof(fp)){
i++;
}
fclose(fp);
printf("The Number Of Sentence In That File: %d",i);
getch();
}
The problem is that there is no advance by calling feof(fp), so the execution halts at the beggining of the file. You need to explicitly call something like, getchar(), fscanf(), fgetc(), etc. Here is an example
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
FILE *fp;
int main() {
fp=fopen("test.txt","r");
int i=0, ch=0;
while((ch = fgetc(fp)) > 0){
if(ch == '\n')
i++;
}
fclose(fp);
printf("The Number Of Sentence In That File: %d\n",i);
getchar();
}
For what you want you can try something like this -
char *s;
s=malloc(255);
while(fscanf(fp,"%254s",s)==1)
{
i++;
}
...
free(s);
This will give desired output.
Also -
while(!feof(fp))
feof to control loop is always wrong .And you should never use feof in loop . Refer here
Your loop does not terminate because you are not doing anything with the file within the loop.
Instead of using feof to control the loop, I would propose to use getline().
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
FILE *fp;
int main() {
fp=fopen("C:\\Users\\Alan\\Desktop\\text.txt","r");
int i = 0;
char *line = NULL;
size_t len = 0;
while (getline(&line, &len, fp) != -1)
i++;
free(line);
fclose(fp);
printf("The Number Of Sentence In That File: %d\n",i);
}
Note: In this case line is set to NULL and len is set 0, hence getline() will allocate a buffer for storing the line. This buffer should be freed before the program returns.
Update
You can use the return value of getline, if you also want to know the number of chars in the file:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
FILE *fp;
int main() {
fp=fopen("C:\\Users\\Alan\\Desktop\\text.txt","r");
int i = 0;
int j = 0;
int read = 0;
char *line = NULL;
size_t len = 0;
while ((read = getline(&line, &len, fp)) != -1) {
i++;
j += read;
}
free(line);
fclose(fp);
printf("The Number Of Lines In That File: %d\n", i);
printf("The Number Of Chars In That File: %d\n", j);
}

Converting Greek words to uppercase

I have to create a function that reads a file called grwords.txt containing around 540000 words which are written in Greek letters.
I have to convert these words to uppercase and fill an array called char **words.
This is what I have so far.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <windows.h>
#include <ctype.h>
void fp();
int main(int argc, char *argv[]) {
SetConsoleOutputCP(1253);
fp();
return 0;
}
void fp(){
char **words;
words = malloc(546490 * sizeof(int *));
for (i = 0; i < 546490; i++)
words[i] = malloc(24 * sizeof(int));
FILE *file;
char *word;
size_t cnt;
file = fopen("grwords.txt", "rt");
if (file == NULL){
printf("File cannot be opened.\n");
exit(1);
}
cnt = 0;
while (1==fscanf(file, "%24s",word)){
if (cnt == 546490)
break;
strcpy(words[cnt++], word);
}
fclose(file);
}
I'm still trying to figure out pointers. I know that & makes a pointer from a value and * a value from a pointer. Updated the program and it successfully fills the array with the words from the file! I still have no idea how to convert Greek lowercase to uppercase.
Handling Greek words can be dependent on your platform.
First of all, you need to understand how file handling works. Here is what I wrote:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define bufSize 1024 // max lenght of word
// we are going to receive the .txt from cmd line
int main(int argc, char *argv[])
{
FILE *fp;
// Assume file has max 10 words
const size_t N = 10;
// Allocate a 2D array of N rows
// and bufSize columns.
// You can think of it like an array
// of N strings, where every string
// has, at most, bufSize length.
char buf[N][bufSize];
// make sure we got the .txt
if (argc != 2)
{
fprintf(stderr,
"Usage: %s <soure-file>\n", argv[0]);
return 1;
}
// open the file
if ((fp = fopen(argv[1], "r")) == NULL)
{ /* Open source file. */
perror("fopen source-file");
return 1;
}
// we will use that for toupper()
char c;
// counters
int i = 0, j;
while (fscanf(fp, "%1024s", buf[i]) == 1)
{ /* While we don't reach the end of source. */
/* Read characters from source file to fill buffer. */
// print what we read
printf("%s\n", buf[i]);
j = 0;
// while we are on a letter of word placed
// in buf[i]
while (buf[i][j])
{
// make the letter capital and print it
c = buf[i][j];
putchar (toupper(c));
j++;
}
i++;
printf("\ndone with this word\n");
}
// close the file
fclose(fp);
return 0;
}
For this test.txt file:
Georgios
Samaras
Γιώργος
Σαμαράς
the code would run as:
./exe test.txt
Georgios
GEORGIOS
done with this word
Samaras
SAMARAS
done with this word
Γιώργος
Γιώργος
done with this word
Σαμαράς
Σαμαράς
done with this word
As you can see, I could read the Greek words, but failed to convert them in upper case ones.
Once you got how file handling goes, you need to use wide characters to read a file with Greek words.
So, by just modifying the above code, we get:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <wchar.h>
#include <wctype.h>
#include <locale.h>
#define bufSize 1024
int main(int argc, char *argv[])
{
setlocale(LC_CTYPE, "en_GB.UTF-8");
FILE *fp;
const size_t N = 15;
wchar_t buf[N][bufSize];
if (argc != 2)
{
fprintf(stderr,
"Usage: %s <soure-file>\n", argv[0]);
return 1;
}
if ((fp = fopen(argv[1], "r")) == NULL)
{
perror("fopen source-file");
return 1;
}
wchar_t c;
int i = 0, j;
while (fwscanf(fp, L"%ls", buf[i]) == 1)
{
wprintf( L"%ls\n\n", buf[i]);
j = 0;
while (buf[i][j])
{
c = buf[i][j];
putwchar (towupper(c));
j++;
}
i++;
wprintf(L"\ndone with this word\n");
}
fclose(fp);
return 0;
}
And now the output is this:
Georgios
GEORGIOS
done with this word
Samaras
SAMARAS
done with this word
Γιώργος
ΓΙΏΡΓΟΣ
done with this word
Σαμαράς
ΣΑΜΑΡΆΣ
done with this word
I see that you may want to create a function which reads the words. If you need a simple example of functions in C, you can visit my pseudo-site here.
As for the 2D array I mentioned above, this picture might help:
where N is the number of rows (equal to 4) and M is the number of columns (equal to 5). In the code above, N is N and M is bufSize. I explain more here, were you can also found code for dynamic allocation of a 2D array.
I know see that you are on Windows. I tested the code in Ubuntu.
For Windows you might want to take a good look at this question.
So, after you read all the above and understand them, you can see what you asked for with dynamic memory management.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include <wctype.h>
#include <locale.h>
#define bufSize 1024
wchar_t **get(int N, int M);
void free2Darray(wchar_t** p, int N);
int main(int argc, char *argv[])
{
setlocale(LC_CTYPE, "en_GB.UTF-8");
FILE *fp;
const size_t N = 15;
wchar_t** buf = get(N, bufSize);
if (argc != 2)
{
fprintf(stderr,
"Usage: %s <soure-file>\n", argv[0]);
return 1;
}
if ((fp = fopen(argv[1], "r")) == NULL)
{
perror("fopen source-file");
return 1;
}
wchar_t c;
int i = 0, j;
while (fwscanf(fp, L"%ls", buf[i]) == 1)
{
wprintf( L"%ls\n", buf[i]);
j = 0;
while (buf[i][j])
{
c = buf[i][j];
putwchar (towupper(c));
j++;
}
i++;
wprintf(L"\ndone with this word\n");
}
fclose(fp);
// NEVER FORGET, FREE THE DYNAMIC MEMORY
free2Darray(buf, N);
return 0;
}
// We return the pointer
wchar_t **get(int N, int M) /* Allocate the array */
{
/* Check if allocation succeeded. (check for NULL pointer) */
int i;
wchar_t **table;
table = malloc(N*sizeof(wchar_t *));
for(i = 0 ; i < N ; i++)
table[i] = malloc( M*sizeof(wchar_t) );
return table;
}
void free2Darray(wchar_t** p, int N)
{
int i;
for(i = 0 ; i < N ; i++)
free(p[i]);
free(p);
}
Note that this code is expected to work on Linux (tested on Ubuntu 12.04), not on Windows (tested on Win 7).

Reading Text In C

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX 500
int main(){
int JourneyId;
char Date[MAX];
int Hour;
char BusDriver[MAX];
char Departure[MAX];
char Destination[MAX];
int BusCapacity;
FILE * file;
file = fopen( "Journey.txt" , "rt");
if(file){
while (fscanf(file,"%d,%s,%d,%20[^,],%20[^,],%20[^,],%d", &JourneyId,Date,&Hour,BusDriver,Departure,Destination, &BusCapacity) != EOF){
printf("%d,",JourneyId);
printf("%s",BusDriver);
}
}
else{
printf("Error");
}
return 1;
}
I want to read text file and use this code for adding BST.But If I run , Output is infinite loop.How can I read text file ?
Text file which I want to read:
80,15.04.2014,10,Henry Ford,NewYork,Paris,45
40,15.04.2014,11,Nikola Tesla,Londra,NewYork,40
Rather than read a text file using fscanf(), strongly recommend using fgets() and then parsing via sscanf(), strtok(), strtol(), etc. Check all function return values. It is much easier to cope with the unexpected - which is certainly what is happening in OP's case.
Using modified format from #BLUEPIXY
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX 500
int main() {
int JourneyId;
char Date[MAX];
int Hour;
char BusDriver[MAX];
char Departure[MAX];
char Destination[MAX];
int BusCapacity;
FILE * file;
file = fopen("Journey.txt", "rt");
if (file) {
char buf[MAX*4 + 20*3 + 6*1 + 3];
while (fgets(buf, sizeof buf, stdin) != NULL) {
int cnt = sscanf(buf, "%d,%499[^,],%d,%499[^,],%499[^,],%499[^,],%d",
&JourneyId, Date, &Hour, BusDriver, Departure, Destination,
&BusCapacity);
if (cnt != 7) {
printf("Unexpected input \"%s\"", buf);
break;
}
printf("%d,", JourneyId);
printf("%s\n", BusDriver);
}
fclose(file); // Be sure to close
} else {
printf("Error opening\n");
}
return 1;
}
As #BLUPIXY indicated, The following functions (tried on SuSE Linux / gcc)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX 500
int main(){
int JourneyId;
char Date[MAX];
int Hour;
char BusDriver[MAX];
char Departure[MAX];
char Destination[MAX];
int BusCapacity;
FILE *file;
file = fopen( "Journey.txt" , "rt");
if(file)
{
// while(fscanf(file,"%d,%s,%d,%20[^,],%20[^,],%20[^,],%d", &JourneyId,Date,&Hour,BusDriver,Departure,Destination, &BusCapacity) != EOF){
while(fscanf(file,"%d,%11[^,],%d,%20[^,],%20[^,],%20[^,],%d", &JourneyId,Date,&Hour,BusDriver,Departure,Destination, &BusCapacity) != EOF){
printf("%d,",JourneyId);
printf("%s",BusDriver);
}
}
else
{
printf("Error");
}
return 1;
}

Resources