I am trying to add a -1 to the end of each line of a file. For instance, file.txt is
1 4 5
2 5 9
3 5 6
but would become
1 4 5 -1
2 5 9 -1
3 5 6 -1
I am figuring out how to add text in general to a file from C, but I cannot figure out how to add the same text to each line in the file, and assure that the new line character is placed after the new last character in the lines (in this case -1).
Here is what I have tried:
FILE *f = fopen("file.txt", "w");
if (f == NULL)
{
printf("Error opening file!\n");
exit(1);
}
/* print some text */
const char *text = " -1";
fprintf(f, "%s\n", text);
Any advice greatly appreciated!
I can add -1 to each line using a text editor, by replacing "\r\n" with " -1\r\n" or similar depending on the file's eol format.
Or programmatically, create a new file like this:
#include <stdio.h>
#include <string.h>
int main()
{
FILE *fr, *fw;
char buffer[10000];
fr = fopen("file.txt","rt");
if (fr == NULL) {
printf("Error opening input file\n");
return 1;
}
fw = fopen("file1.txt","wt");
if (fw==NULL) {
printf("Error opening output file\n");
fclose (fr);
return 1;
}
while (fgets(buffer, 10000, fr) != NULL) {
buffer [ strcspn(buffer, "\r\n") ] = 0; // remove trailing newline etc
fprintf(fw, "%s -1\n", buffer);
}
fclose(fw);
fclose(fr);
return 0;
}
Output file:
1 4 5 -1
2 5 9 -1
3 5 6 -1
Simply read each char, one at a time and print the suffix when the end-of-line detected. Then print the character read.
void Append(FILE *inf, FILE *outf, const char *suffix) {
int ch;
for (;;) {
int ch = fgetc(inf);
if (ch == '\n' || ch == EOF) {
fputs(suffix, outf);
if (ch == EOF) {
break;
}
}
fputc(ch, outf);
}
}
// Error checking omitted
char tmp[L_tmpnam];
tmpnam(tmp);
FILE *inf = fopen("file.txt", "r");
FILE *outf = fopen(tmp, "w");
Append(inf, outf, " -1");
fclose(inf);
fclose(outf);
remove("file.txt");
rename(tmp, "file.txt");
If you agree to use two seperate files for input and output, your job will be very easy. The algorithm to achieve what you want can be designed like below
Open the input file, open the output file. [fopen()]
define a string with the constant input value that you want to add after each line. [char * constvalue = "-1";]
Read a line from the input file. [fgets()##]
use fprintf() to write the data read from the input file and the constant value, together. Some pseudocode may look like
fprintf(outfile, "%s %s", readdata, constvalue);
loop untill there is value in the input file [while (fgets(infile....) != NULL)]
close both the files. [fclose()]
## -> fgets() reads and stores the trailing newline \n to the supplied buffer. You may want to remove that.
Related
I have this code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE* ptr = fopen("data.txt","r");
char filename[100];
if (ptr==NULL)
{
printf("no such file.");
return 0;
}
char buf[100];
while (fscanf(ptr,"%*s %*s %s ",buf)==1)
printf("%s\n", buf);
printf("Create a file \n");
scanf("%s", filename);
fptr2 = fopen(filename, "w");
if (fptr2 == NULL)
{
printf("Cannot open file %s \n", filename);
exit(0);
}
c = fgetc(fptr1);
while (c != EOF)
{
fputc(c, fptr2);
c = fgetc(fptr1);
}
printf("\nContents copied to %s", filename);
fclose(fptr1);
fclose(fptr2);
return 0;
}
}
It coppies full content from one file to another. I need to copy only strings that have 5 as the last character (3 column)
For example Data.txt looks like that:
Alex 10B 4
John 10A 3
Kate 10C 5
In file that I will create during execution has to be coppied only Kate 10C 5 string. I've been trying for hours but I don't know how to do this. Can you help me?
In the end of each line there is a newline character, (\n) you can use that to read line by line and copy only the ones that you want:
FILE* dest = fopen("out.txt", "w+"); // supressed null check for simplicity
char buf[100];
char* char_to_find;
// parse line by line
while (fscanf(ptr, " %99[^\n]", buf) == 1){
char_to_find = buf;
// reach the end of the line
while(*char_to_find){
char_to_find++;
}
//move one back
char_to_find--;
// if it's 5 save, if not move on
if(*char_to_find == '5' && *(char_to_find - 1) == ' '){
fputs(buf, dest);
}
}
Live demo
The problem is that the function call
while (fscanf(ptr,"%*s %*s %s ",buf)==1)
consumes the input from the input stream, so that it is no longer available for copying. You are only saving the contents of the last field, but all other data is lost.
I suggest that you read one line at a time into a memory buffer, by calling the function fgets in a loop. That way, you will process one line of input per loop iteration, and will be saving the contents of the entire line.
In every loop iteration, you can use sscanf on this memory buffer to determine whether the third field has the desired value, and if it does, then you copy the entire line to the output file. Otherwise, you do nothing and proceed to the next line (i.e. the next loop iteration).
char line[100];
//process one line of input per loop iteration
while ( fgets( line, sizeof line, input_file ) != NULL )
{
char third_field[20];
if (
//third field was successfully extracted
sscanf( line, "%*s%*s%19s", third_field ) == 1
&&
//third field contains the string "5"
strcmp( third_field, "5" ) == 0
)
{
//copy entire line to output file
fputs( line, output_file );
}
}
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE* ptr = fopen("data.txt","r");
char filename[100];
if (ptr==NULL)
{
printf("no such file.");
return 0;
}
printf("Create a file \n");
scanf("%s", filename);
FILE* dest = fopen(filename, "w+"); // check for null like above
char buf[100];
char* char_to_find;
while (fscanf(ptr,"%99[^\n] ", buf) == 1){
char_to_find = buf;
while(*char_to_find != 0){
char_to_find++;
}
char_to_find--;
if(*char_to_find == '5'){
printf("%s\n", buf); // test ptint
fputs(buf, dest);
}
}
}
I'm new to programming in C. And I'm trying to print the first 10 lines of a text file. When I run my program with a text file containing 11 lines of text, only the first line is displayed. I'm not sure why it does that, but I suspect there is something wrong in my while loop. Can someone please help me?
#include <stdio.h>
int main(int argc, char *argv[]){
FILE *myfile;
char content;
int max = 0;
// Open file
myfile = fopen(argv[1], "r");
if (myfile == NULL){
printf("Cannot open file \n");
exit(0);
}
// Read the first 10 lines from file
content = fgetc(myfile);
while (content != EOF){
max++;
if (max > 10)
break;
printf ("%c", content);
content = fgetc(myfile);
}
fclose(myfile);
return 0;
}
You have been already advised to use fgets. However, if your file has lines of unknown length, you may still want to use fgetc. Just make sure you count only newlines, not all characters:
int max = 0;
int content;
while ((content = fgetc(myfile)) != EOF && max < 10){
if (content == '\n') max++;
putchar(content);
}
fgetc() returns the next character in the file, not the next line. You probably want to use fgets() instead, which reads up to the next newline character into a buffer. Your code should probably end up with something like:
// allocate 1K for a buffer to read
char *buff = malloc(1024);
// iterate through file until we are out of data or we read 10 lines
while(fgets(buff, 1024, myfile) != NULL && max++ < 10) {
printf("%s\n", buff);
}
free(buff);
// close your file, finish up...
Read more about fgets() here: https://www.tutorialspoint.com/c_standard_library/c_function_fgets.htm
fgetc function reads the next character not the next ine. for reading the number of lines you should use fgets function. this function reads the full string till the end of the one line and stores it in a string.
your code Shuld be as:-
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *myfile;
char content[200];
int max = 0;
// Open file
myfile = fopen(argv[1], "r");
if (myfile == NULL)
{
printf("Cannot open file \n");
exit(0);
}
// Read the first 10 lines from file
fgets(content, 200, myfile);
while (content != EOF)
{
max++;
if (max > 10)
break;
printf("%s", content);
fgets(content, 200, myfile);
}
fclose(myfile);
return 0;
}
I'm currently working on making a tiny computer in C for a programming assignment and I'm stuck on one part.
I'm stuck on how to correctly ignore comments in a text file that I'm reading in. (Example of file input below).
Input File
5 5 //IN 5
6 7 //OUT 7
3 0 //STORE 0
5 5 //IN 5
6 7 //OUT 7
3 1 //STORE 1
1 0 //LOAD 0
4 1 //SUB 1
3 0 //STORE 0
6 7 //OUT 7
1 1 //LOAD 1
6 7 //OUT 7
7 0 //END
The first input on each new line is an operation, the 2nd input being an address. I am planning to have a switch statement for each op and then calling the appropriate function. This is my current layout for reading in the file:
//file handling
int c;
FILE * file;
file = fopen(name, "r");
if (file){
printf("Run.\n");
while ((c = getc(file)) != EOF){
op = c;
switch (op){
case 5:
print("Inside case 5\n");
}
}
fclose(file);
}
How can I ignore the // on each line and skip to the next line in the file?
Call fgets to get a full line:
fgets(buffer, 100, file);
and then extract the two numbers from the line:
sscanf(buffer, "%d%d", &instruction, &address);
how to correctly ignore comments in a text file that I'm reading in
How can I ignore the // on each line and skip to the next line in the file?
Read the line using fgets()
char buf[80];
if (fgets(buf, sizeof buf, file)) {
Look for the // with strstr() #Steve Summit and lop off the string at that point.
char *slash_slash = strstr(buf, "//");
if (slash_slash) {
*slash_slash = '\0';
}
Continue processing the line as desired.
...
}
By using fgets and strtok you can read line by line and split the string acording to the // delimiter. Here's an example (it is not fully checked, but it's the main idea):
FILE *f = fopen("file.txt", "r");
if (f== NULL)
{
printf("opening file failed\n");
return 1;
}
char buf[256] = { 0 };
while (fgets(buf, 256, f))
{
char *s = strtok(buf, "//");
if (s == NULL)
{
printf("s == NULL\n");
}
else
{
printf("%s\n", s);
}
memset(buf, 0, 256);
}
fclose(f);
EDIT: I just realized that this is not exactly what you were looking for. However, you can still use it in order to first ignore the comment, and then break the given string into operation and address, or whatever that is...
So basically the text file would look like this
Starting Cash: 1500
Turn Limit (-1 for no turn limit): 10
Number of Players Left To End Game: 1
Property Set Multiplier: 2
Number of Houses Before Hotels: 4
Must Build Houses Evenly: Yes
Put Money In Free Parking: No
Auction Properties: No
Salary Multiplier For Landing On Go: 1
All I need from the file is basically anything after ":"
I'm just confused how to only read anything after a ":"?
This is what I have right now. I just can't seem to think of a way to only scan for the numbers/yesorno.
void readRules(char*file_name)
{
Rules r;
FILE *file = NULL;
file = fopen(file_name, "r");
if (file == NULL) {
printf("Could not open %s\n", file_name);
return;
}
char c=fgetc(file);
fscanf(file, "%c", &c);
while (!feof(file))
{
fscanf(file, "%c", &c);
if(c==':')
{
r.startCash=c;
}
}
printf("There are %c word(s).\n", r.startCash);
fclose(file);
}
Thank you.
This program will read integers following a colon in each line of the file given. I imagine this is appropriate? You also have some strings after colons. If you want to read those, you can try scanning for a string "%s" and testing if the function returns nonzero (for at least one format pattern matched).
#include <stdio.h>
#include <stdlib.h>
#define MAXLINE 1000
void readRules (const char *filename) {
FILE *fp;
char *lp, line[MAXLINE];
int n;
// Return early if file cannot be opened.
if ((fp = fopen(filename, "r")) == NULL) {
fprintf(stderr, "Error: Couldn't open \"%s\"!\n", filename);
return;
}
// Use fgets to read consecutive lines. Returns NULL on error or EOF.
while (fgets(line, MAXLINE, fp) != NULL) {
// Read until newline is hit or buffer size exceeded.
for (lp = line; *lp != '\n' && (lp - line) < MAXLINE; lp++) {
// If encounter colon and sccanf reads at least 1 integer..
if (*lp == ':' && sscanf(lp + 1, "%d", &n) == 1) {
fprintf(stdout, "%d\n", n);
break;
}
}
}
// Clean up.
fclose(fp);
}
int main (int argc, const char *argv[]) {
readRules("test.txt");
return 0;
}
When run with your example input, it produces:
1500
10
1
2
4
1
I have created a function that takes as a parameter the name of a source file, the name of a destination file and the beginning and end lines of the source file lines that will be copied to the destination file, like the example below. All I want to do is to input the lines that I want to copy to the other text file like the example below:
The code I show you just "reads" the content of the one text file and "writes" another one. I want to "write" specific lines that the user gives, not the whole text file
Inputs by the user:
Source_file.txt //the file that the destination file will read from
destination_file.txt //the new file that the program has written
2 3 // the lines that it will print to the destination file: 2-3
Source_file.txt:
1
2
3
4
5
6
destination_file.txt
2
3
code:
#include <stdio.h>
#include <stdlib.h>
void cp(char source_file[], char destination_file[], int lines_copy) {
char ch;
FILE *source, *destination;
source = fopen(source_file, "r");
if (source == NULL) {
printf("File name not found, make sure the source file exists and is ending at .txt\n");
exit(EXIT_FAILURE);
}
destination = fopen(destination_file, "w");
if (destination == NULL) {
fclose(source);
printf("Press any key to exit...\n");
exit(EXIT_FAILURE);
}
while ((ch = fgetc(source)) != EOF)
fputc(ch, destination);
printf("Copied lines %d from %s to %s \n",
lines_copy, source_file, destination_file, ".txt");
fclose(source);
fclose(destination);
}
int main() {
char s[20];
char d[20];
int lines;
printf("-Enter the name of the source file ending in .txt\n"
"-Enter the name of the destination file ending in .txt\n"
"-Enter the number of lines you want to copy\n\n");
printf(">subcopy.o ");
gets(s);
printf("destination file-> ");
gets(d);
printf("Lines: ");
scanf("%d", &lines);
cp(s, d, lines);
return 0;
}
In cp(), in order to select the lines to keep, you have to know their position in the input-file. Thus, you need to count lines.
Using fgets instead of fgetc will allow you to count the lines.
On the other hand, if I wanted to select lines 3 and 7 to 12 in a file, I'd use:
sed -n -e "3p;7,12p" < input.txt > output.txt
this is a very simple solution, let's say you know that the maximun length of a line will be 100 characters for simplicity (if a line is longer than 100 characters only the first 100 will be taken)
at the top (outside main) you can write
#ifndef MAX_LINE_SIZE
#define MAX_LINE_SIZE 100
#endif
i know many people don't like this but i think in this case it makes the code more elegant and easier to change if you need to modify the maximum line size.
to print only the wanted lines you can do something like this
char line[MAX_LINE_SIZE];
int count = 0;
while (fgets(line, MAX_LINE_SIZE, source)){
count++;
if (3 <= count && count <= 5){
fputs(line, destination);
}
}
The while loop will end when EOF is reched because fgets returns NULL.
P.S. there could be some slight errors here and there since i wrote it pretty fast and going by memory but in general it should work.
There are some problems in your program:
Do not use gets(), it may cause buffer overflows.
Always use type int to store the return value of fgetc() in order to distinguish EOF from regular byte values.
You pass an extra argument ".txt" to printf(). It will be ignored but should be removed nonetheless.
To copy a range of lines from source to destination, you can just modify your function this way:
#include <stdio.h>
#include <string.h>
#include <errno.h>
void cp(char source_file[], char destination_file[], int start_line, int end_line) {
int ch;
int line = 1, lines_copied;
FILE *source, *destination;
source = fopen(source_file, "r");
if (source == NULL) {
printf("Cannot open input file %s: %s\n",
source_file, strerror(errno));
exit(EXIT_FAILURE);
}
destination = fopen(destination_file, "w");
if (destination == NULL) {
printf("Cannot open output file %s: %s\n",
destination_file, strerror(errno));
fclose(source);
exit(EXIT_FAILURE);
}
while ((ch = fgetc(source)) != EOF) {
if (line >= start_line && line <= end_line) {
fputc(ch, destination);
}
if (ch == '\n') {
line++;
}
}
lines_copied = 0;
if (line > start_line) {
if (line >= end_line) {
lines_copied = end_line - start_line + 1;
} else {
lines_copied = line - start_line + 1;
}
}
printf("Copied lines %d from %s to %s\n",
lines_copy, source_file, destination_file);
fclose(source);
fclose(destination);
}
int main() {
char source_file[80];
char destination_file[80];
int start_line, end_line;
printf("-Enter the name of the source file ending in .txt\n"
"-Enter the name of the destination file ending in .txt\n"
"-Enter the start and end line\n\n");
printf(">subcopy.o ");
if (scanf("%79s", source_file) != 1) {
return 1;
}
printf("destination file-> ");
if (scanf("%79s", destination_file) != 1) {
return 1;
}
printf("Start and end lines: ");
if (scanf("%d %d", &start_line, &end_line) != 2) {
return 1;
}
cp(source_file, destination_file, start_line, end_line);
return 0;
}