How to auto append newline at the end of a file - c

I am newbie and have a C - Linux program that read a number of variable lines like this:
12 34 56 78
3 4 7 900
...
%d %d %d %d
...
1 2 3 4
The function I've written so far is like this:
void Import(const char* path_of_file)
{
FILE *cfile = fopen(path_of_file, "r");
int lines = 0;
//I copied it from another question
while (EOF != (fscanf(cfile,"%*[^/n]"), fscanf(cfile, "%*c"))) ++lines;
fclose(cfile);
cfile = fopen(path_of_file, "w");
...
for( i=0; i<n; i++)
{
...
fscanf(cfile, "%d %d %d %d", &a, &b, &c, &d);
...
}
...
//Of course it will return something, but it shouldn't matter here
fclose(cfile);
}
But may be because the text file is created in Windows or some thing, it doesn't always end with a newline, and so my program frequently miss the last line.
Is there anyway to automatic append a newline at the end of file if it's not there? Or better, is there any way to read the last line without that newline? A example function based on the one above will be very good.

Thank you Pavel, I have never read the other answer in that post, my fault for only read the Accepted answer. After read all those posts, I chosen to use this code to count the line, it can avoid the problem above:
int n = 0;
int pc = EOF;
int c;
while ((c = getc(cfile)) != EOF) {
if (c == '\n')
++n;
pc = c;
}
if (pc != EOF && pc != '\n')
++n;
Sorry for my stupidness.

Related

Copying the input from `getchar()` to another variable

In the following code example from K&R's book, if I replace putchar(c) with printf("%c", c) the code works the same. But if I replace it with printf("%d", c) it gives gibberish output.
#include <stdio.h>
int main() {
int c;
c = getchar();
while (c != EOF) {
putchar(c);
c = getchar();
}
}
From here, I learned that the getchar() converts the stdin to an 8-bit character whose value ranges from 0 to 255.
Now I want to print the value of c using putchar(c) in one line and printf("%d", c) in another line. So I wrote the following code:
#include <stdio.h>
int main() {
int c, b;
c = getchar();
b = c;
while (c != EOF && c != 10) {
printf("%c",c);
c = getchar();
}
printf("\n");
while (b != EOF && b != 10) {
printf("%d\t",b);
b = getchar();
}
}
I used the condition c != 10 as the newline character is read as 10 by getchar(). I expected the code to work as
$ ./a.out
783
783
55 56 51
but the program terminates as
$ ./a.out
783
783
55
I understand that getchar() takes input from stdin and the variable b is not stdin. So how should I copy the variable c to b so that my program works as I expect it to?
The problem is that your code does not (and cannot, as it stands) 'remember' the inputs you gave in the first loop. So, after you have finished that loop, your second loop is wanting to read in the characters for b (after it has output the first value, which is remembered from the earlier b = c line).
So, after outputting 55 (the integer value of the character 7), it is waiting for further input.
Probably the easiest way to get the output that you're looking for is to have an array of input characters. Then, you can output the %c values as you read them (as before), then re-run the outputs using the %d format in a subsequent for loop.
Here is a demonstration that does what I think you're after:
#include <stdio.h>
#define MAXINS 20 // Set to the maximum number of input characters you want to allow
int main()
{
int c[MAXINS];
int i = 0, n = 0;
c[0] = getchar();
while (i < MAXINS && c[i] != EOF && c[i] != 10) {
printf("%c", c[i]);
c[++i] = getchar();
++n;
}
printf("\n");
for (i = 0; i < n; ++i) {
printf("%d\t", (int)(c[i]));
}
return 0;
}
Feel free to ask for further clarification and/or explanation.
EDIT: On the point in the your first paragraph, "But if I replace it with printf("%d", c) it gives gibberish output." Well, when I try the following code and give 783 and then hit return (which generates a newline) I get the expected 55565110 as the output:
int main()
{
int c;
c = getchar();
while (c != EOF) {
printf("%d", c);
c = getchar();
}
return 0;
}
This may look like gibberish, but it's just the same output as you 'expect' in your later code, but without the spaces and with the addition of the 10 for the newline.
You need to have every character stored, because once you read a char from stdin, it is not present in stdin anymore.
Since you want the newline character in the end as a part of the input, you should use fgets to take the input.
Say you are taking an input that could have a maximum of 100 characters.
#include <stdio.h>
int main(void) {
char c[100]; // A char array
fgets(c,100,stdin);
int x=0;
while (c[x] != 10 && c[x] != EOF)
printf("%c",c[x++]);
printf("\n");
x = 0;
while (c[x] != 10 && c[x] != EOF) // You can simply compare it with the newline character too.
printf("%d ",c[x++]);
printf("\n");
return 0;
}
There are many ways to do this. You can also read stdin character-by-character ans store it in an array. However, since you need to display the ASCII values of the characters in another line after displaying the characters themselves, you will have to store them in an array.
You are copying only the first input, to copy the whole string you need to store each input in a buffer and check if the string doesn't overflow that buffer on each iteration:
int main(void)
{
enum {size = 256};
char buffer[size];
size_t count = 0;
int c;
while ((c = getchar()) && (c != '\n') && (c != EOF))
{
printf("%c", c);
if (count < size)
{
buffer[count++] = (char)c;
}
}
printf("\n");
for (size_t iter = 0; iter < count; iter++)
{
printf("%d\t", buffer[iter]);
}
printf("\n");
}
If you don't want to limit the buffer to an arbitrary size then you need to change your approach to use dynamic memory (realloc or a linked list)

read a file and save as a matrix

i have a file like that :
1 100
2 200
3 300
4 400
1
i want to save it as a matrix and i want to save NULL if there is no second number !
i tried to write the program but it does not work correctly !
#include<stdio.h>
int main() {
int k=0 ,i,j , arr[100][100];
FILE *in= fopen("file.txt","r");
char line[1000];
while(fgets(line,1000,in) !=NULL) k++;
fgets(line,1000,in);
for (i=0;i<k;i++){
for (j=0;j<2;j++){
int tmp ;
fscanf(in ,"%d", &tmp) ;
arr[i][j] = tmp ;
}
}
fclose(in);
return 0; }
Two major problems:
The first is that the first loop will read all lines, even the one with the single number on the line. That means the lonely fgets call will not do anything, and more importantly that the value of k will be wrong.
The second problem is that once you read all data from the file, you don't go back to the beginning of the file, instead you continue to try and read from beyond the end of the file.
The first problem can be solve by skipping the second fgets call, and decreasing k by one.
The second problem can be solved by calling rewind after you counted the number of lines.
Also when you actually read the numbers, you don't need the inner loop, just do e.g.
scanf("%d %d", &arr[i][0], &arr[i][1]);
Actually, you don't need the first line-counting loop at all, you can do it all in a single loop, by using fgets and sscanf and then checking the return value of sscanf. So your program could look something like
#include <stdio.h>
int main(void)
{
int values[100][2];
FILE *input = fopen("file.txt", "r");
size_t entries = 0;
if (input != NULL)
{
char buffer[40];
while (fgets(buffer, sizeof(buffer), input) != NULL && entries < 100)
{
int res = sscanf(buffer, "%d %d", &values[entries][0], &values[entries][1]);
if (res <= 1 || res == EOF)
{
// Read the last line with only one number, or an error happened
values[entries][0] = 0;
values[entries][1] = 0;
break;
}
++entries;
}
if (ferror(input))
{
printf("Error reading file\n");
}
fclose(input);
}
// All done, the number of "records" or "entries" is in the variable entries
// Example code: print the values
for (size_t i = 0; i < entries; ++i)
printf("Line %d: %d %d\n", i + 1, values[i][0], values[i][1]);
return 0;
}

Unable to read in file -- C

I'm sorry, I've done something similar to this before and I'm sure I'm over complicating this, but could someone help me understand whats wrong? I've only known java previously, but I'm getting familiar with C.
I have tried 3 different ways from searches online, the one not commented out is the one I'd prefer to use. It's printing out the right amount of numbers in data.txt but it only prints out the number 1. I thought the c = scanf inside the while would give me a different result each time.
I also tried just reading in the numbers as a char since I'm not doing any math, but I got a bunch of funky symbols.
input:
./a.out < data.txt
data.txt contents:
0 2 2
0 6 1
0 7 4
1 7 5
0 8 2
0 8 9
1 15 13
c file content:
#include
#include "queue.h"
int main(void)
{
/*
char c = scanf("%c", &c);
while (c!= EOF)
{
printf("%c", c);
c = scanf("%c", &c);
}//while
*/
int c = scanf("%d", &c);
while (c!= EOF)
{
printf("%d", c);
c = scanf("%d", &c);
}//while
printf("\n");
/*
char c;
//char **argv
FILE *infile;
infile=fopen(argv,"r");
while (!feof(infile))
{
fscanf(infile, "%c", &c);
printf("%c", c);
} // while
fclose(infile);
*/
return 0;
}
You should use a different variable for checking the result of scanf than for storing the value read. As you have it now, you immediately overwrite the read value with the scanf result.
Also, it is better to check for success than to check for EOF, as if there is text entered you will go into an infinite loop.
int x = scanf("%d", &c);
while ( x == 1 )
{
printf("%d", c);
x = scanf("%d", &c);
}
Obviously this can be condensed:
while ( 1 == scanf("%d", &c) )
printf("%d", c);

C filling an array from a text file

I'm trying to fill an array from a text file. I'm using fgetc and my problem is dealing with the newline characters that are in the text file. I've currently got,
for(i = 0; i < rows; i++){
for(j = 0; j < columns; j++){
if((fgetc(fp) == '\n') || (fgetc(fp) == '\r')){
fgetc(fp);
array[i][j] = fgetc(fp);
else{
array[i][j] = fgetc(fp);
}
printf("i %d j %d char %c code %d\n", i, j, array[i][j], array[i][j]);
}
}
The idea is that if there's a newline character I want to advance the file pointer while in the same i,j position of the loop so I can get the next character. The output for this is jumbled for the first two rows and then it starts reading characters with character code -1. Am I doing something terribly wrong?
Each call to fgetc will advance the file pointer. Try calling it once:
int c = fgetc(fp);
then test the value of c. Store it if you want or go through the loop again.
In your first if() statement, there's a bit of an issue. When you do this:
if((fgetc(fp) == '\n') || (fgetc(fp) == '\r')){
fgetc(fp);
array[i][j] = fgetc(fp);
You actually are calling fgetc(fp) four times. Twice in the if() statement, twice later on.
Perhaps you are looking more for something like this:
for(i = 0; i < rows; i++){
for(j = 0; j < columns; j++){
int test = fgetc(fp);
if(test != '\n' && test != '\r')
array[i][j] = test;
//We want to "undo" the last j++ if we got a whitespace
else
j--;
printf("i %d j %d char %c code %d\n", i, j, array[i][j], array[i][j]);
}
}
In this example, you call fgetc(fp) exactly once per iteration, and if it's not a \n or \r, you put it in your array.
I'm sorry, I have little experience with fgetc(). If you notice something incredibly awful with what I've done, please notify me!
I can immediately see one source of error. In the following line:
if((fgetc(fp) == '\n') || (fgetc(fp) == '\r'))
There are 2 calls to fgetc(). This means that if the first call does not return '\n', another call will be made whose return value is then compared to '\r'. This has the effect of advancing the file pointer twice, as the pointer is advanced each time you call fgetc . A better way to do this would be to fetch one character and then test whether it is '\n' or '\r', and only then incrementing the file pointer with another call to fgetc if this is true. For example:
char letter = fgetc(fp);
if((letter == '\n') || (letter == '\r')
...
...
Try this and see if you still get the same error.
I believe you are getting the character in your evaluation statement twice. Also, typically the CRLF (carriage return and line feed) end of line characters can be two characters. Read http://en.wikipedia.org/wiki/Newline for details on this.
#include <stdio.h>
int main ()
{
FILE *fp;
int c;
fp = fopen("file.txt","r");
if(fp == NULL)
{
fprintf(stderr,"Error opening file");
return(-1);
}
do
{
c = fgetc(fp);
if ((c == '\n') || (c == '\r')) {
fgetc(fp); // skip CR or LF and advance a character
} else {
printf("%c", c); // print all other characters
}
}while(c != EOF);
fclose(fp);
return(0);
}
This was a quick hit at the code from memory. I don't have a compiler readily available but I think it is correct.

fscanf can't read the first integer of my file input in C but reads the rest

My program needs to read input from a file. The file has a format "int int int" and then some asterisks to indicate that you need to stop reading there. I want to store them in an array of struct and I did. But it seems like my program can't read the very first integer of the input file. I checked it with printf and I can't do anything about it. Help please. Here's the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct points{
int i;
int x;
int y;
};
int main(){
int lines = 0;
char c, e;
int i, j, x ,y, a, b, temp ;
FILE *fp;
fp = fopen("input.txt", "r");
if (fp != NULL){
while ((e = fgetc(fp)) != '*'){
if (c == '\n'){
lines++;
}
fscanf(fp, "%d%d%d", &i, &x, &y);
struct points pt[lines];
for (j = 0; j <= lines; j++){
pt[j].i = i;
pt[j].x = x;
pt[j].y = y;
printf("%d ", pt[j].i);
}
for (a = 0; a<=lines; a++){
for (b = a + 1; b <= lines; b++){
if (pt[a].x > pt[b].x){
temp = pt[a].x;
pt[a].x = pt[b].x;
pt[b].x = temp;
}
}
}
}
}
else{
printf("Cannot open File!\n");
}
printf("lines = %d\n", lines);
return 0;
}
Your code:
while ((e = fgetc(fp)) != '*') {
if (c == '\n'){
lines++;
}
fscanf(fp, "%d%d%d", &i, &x, &y);
will read the first character and throw it away if it is NOT an asterisk, and will then attempt to read 3 integers AFTER that first character it threw away. If that first character was a digit, then it will look like you 'lost' (part of) the first number.
You also have the problem that you seem to be trying to read the values into a block-local array pt that exists for a single iteration of the while loop (so its recreated with no (garbage) contents each iteration), and then you want to use it after the loop where it is out of scope (so this code won't compile).
What you want is probably something more like:
#define MAX_POINTS 100
struct points pt[MAX_POINTS];
int i = 0;
while (i < MAX_POINTS && 3 == fscanf(fp, "%d%d%d", &pt[i].i, &pt[i].x, &pt[i].y)) {
printf("%d ", pt[i].i);
i++;
}
for (int a = 0; a <= i; a++) {
for (int b = a+1; b <= i; b++) {
:
Note that this reads integers up until it finds something that doesn't look like an integer (such as an asterisk, but could be anything else, including an end-of-file), rather than reading until it finds an asterisk. If you want to read until you see an asterisk, you need to decide what to do with anything that is neither an asterisk or an integer.
Edit
for your alternate question of how to read numbers up to *** and then read more numbers after them (and possibly more stars), you could use something like:
int val;
char buffer[20];
do {
/* start of a group */
while (1 == fscanf(fp, "%d", &val)) {
/* read an integer within a group */
}
/* fp is at EOF or something not an integer. */
/* so read it and loop if its '***' */
} while (1 == fscanf(" %19[*]", &buf) && !strcmp(buf, "***"));
Have you tried using the format string "%d %d %d" instead of "%d%d%d" (i.e. with spaces)?
Also, there are several other problems I see:
You use a while loop to find the first '*' in the line, but then you ask fscanf to parse 3 ints starting at that location. It may not be able to find an int by looking at a '*'...
You also declare the variable struct points pt[lines]; in the middle of a block; that is not valid C syntax.
Once you fix these things, the problem may be fixed.

Resources