i'm trying to read variables from a txt file.
The file .txt is like:
john 10
mark 230
peter 1
I would like to transfer and save this values in an array, for example array[0] = 10, array[1] = 230 etc without minding of names. I pasted my code below and I would like to know how can i edit it using this code below
int conf[4], i = 0, c;
FILE *file_conf;
file_conf = fopen("conf.txt", "r");
if(file_conf == NULL){
fprintf(stderr, "Error\n");
exit(EXIT_FAILURE);
} else {
while((c = fgetc(file_conf)) != EOF) {
fscanf(file_conf, "%d", &conf[i]);
printf("%d\n", conf[i]);
i++;
}
}
You should not be using fgetc() at all--that gets a single character. Instead, add the name format to your fscanf(), something like this:
char name[100];
fscanf(file_conf, "%s %d", name, &conf[i]);
You can prefix scanf() family conversion specifiers with * to suppress assignment. Note that in the posted code, failure to check the value returned from fscanf() could lead to problems with malformed input. Also, the input loop should exit when the array index i grows too large to avoid buffer overflow. The following code exits the loop when i is too large, or when malformed input is encountered:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int conf[4], i = 0;
FILE *file_conf;
file_conf = fopen("conf.txt", "r");
if(file_conf == NULL){
fprintf(stderr, "Error\n");
exit(EXIT_FAILURE);
} else {
while(i < 4 && fscanf(file_conf, "%*s%d", &conf[i]) == 1) {
printf("%d\n", conf[i]);
i++;
}
}
fclose(file_conf);
return 0;
}
Output using using the posted sample input:
10
230
1
Related
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;
}
I searched through and didn’t get a quite working answer. Although I know that still there might be plenty of answers out there. Honestly I couldn’t find it as I am a beginner to C/C++ .
My problem is I have a text file which has data on it separated by pipes('|'). Actually a log file. In each entry things are separated by pipes('|') and each entry is separated by new line('\n')its really lengthy. So I wanted to do is that when user gives a sequence sequence=[2,5,7] the function should be able to read that array and give only the things starting with that pipe position. So here It should give 2nd ,5th, and 7th things in to a text file. down here is the code I used. It doesnt work for some reason I can't find. It gives the resulting text file printed out only with the '\n' and no more.Its more thant the entries in the file too.
minorSeparatorChar is the charactor given as '|'
majorSeparatorChar is the charactor given as '\n'
inFile Input text file
outFile output text file
minSepCount minor separator count
majSepCount major separator count
sequence is a global const int array
void getFormattedOutput(char * inFile, char * outFile, char minorSeparatorChar,char majorSeparatorChar){
FILE *readFile,*writeFile;
int charactor=0, minSepCount=0, i=0,majSepCount = 0;
int flagMin = 0;
char charactorBefore = NULL;
readFile = fopen(inFile,"r"); // opens the file for reading
writeFile = fopen(outFile,"w"); // opens the file for writing
if (readFile==NULL || writeFile == NULL){
printf("\nFile creation is not a sucess, Exiting program..\n");
exit(0);
}
while(charactor!=EOF){
charactorBefore = charactor;
if (charactor==minorSeparatorChar)
flagMin=1;
charactor = fgetc(readFile);
if(charactorBefore == minorSeparatorChar){
flagMin = 0;
if (minSepCount==sequence[i]){
fputc(charactor,writeFile);
continue;
}
i++;
minSepCount++;
}
else if (charactorBefore == majorSeparatorChar){
minSepCount=0;
i=0;
majSepCount++;
fputc('\n',writeFile);
}
else{
if(flagMin==1)
fputc(charactor,writeFile);
continue;
}
}
fclose(readFile);
fclose(writeFile);
}
for example if the input file has
33|333|67|787|7889|9876554|56
20151001|0|0|0|0||94|71
1|94|71|1|94|71|1
and if I give sequence [2,5,6]
It should print to out file as
67 9876554 56
0 94 71
71 71 1
I ultimately concluded that there were too many flags and controls and variables in your code and that I couldn't make head or tail of what they were up to, and decided to rewrite the code. I couldn't see in your code how you knew how many fields were in the sequence, for example.
I write in C11 (C99), but in this program, that simply means that I declare variables when they're needed, not at the top of the function. If it's a problem (C89/C90), move the declarations to the top of the function.
I also find that the names used were so long that they obscured the purpose of the variables. You may think I've gone too far in the other direction; more significantly, your professor (teacher) may think that. So be it; names are fungible and global search and replace works well.
I also don't see how your code is supposed to interpolate semi-arbitrary numbers of blanks between the fields, so I've actually ducked the issue. This code outputs the field separator (minor_sep — a length reduction of minorSeparatorChar) and the record separator (major_sep — reduced from majorSeparatorChar) at the appropriate points.
I note that field numbers start with field 0 in your code. I'm not convinced your code would ever output data from field 0, but that is somewhat tangential given the rewrite.
I ended up with:
#include <stdio.h>
#include <stdlib.h>
static const int sequence[] = { 2, 5, 7 };
static const int seqlen = 3;
static
void getFormattedOutput(char *inFile, char *outFile, char minor_sep, char major_sep)
{
FILE *ifp = fopen(inFile, "r"); // opens the file for reading
FILE *ofp = fopen(outFile, "w"); // opens the file for writing
if (ifp == NULL || ofp == NULL)
{
printf("\nFile creation is not a success, Exiting program..\n");
exit(0);
}
int c;
int seqnum = 0;
int fieldnum = 0;
while ((c = getc(ifp)) != EOF)
{
if (c == major_sep)
{
putc(major_sep, ofp);
fieldnum = 0;
seqnum = 0;
}
else if (c == minor_sep)
{
if (seqnum < seqlen && fieldnum == sequence[seqnum])
{
putc(minor_sep, ofp);
seqnum++;
}
fieldnum++;
}
else if (fieldnum == sequence[seqnum])
fputc(c, ofp);
}
fclose(ifp);
fclose(ofp);
}
int main(void)
{
getFormattedOutput("/dev/stdin", "/dev/stdout", '|', '\n');
return 0;
}
When I run it (I called it split, though it isn't a good choice since there is also a standard command split), I get:
$ echo "fld0|fld1|fld2|fld3|fld4|fld5|fld6|fld7|fld8|fld9" | ./split
fld2|fld5|fld7|
$ echo "fld0|fld1|fld2|fld3|fld4|fld5|fld6" | ./split
fld2|fld5|
$
The only possible objection is that there is a field terminator rather than a field separator. As you can see, a terminator is not hard to implement; making it into a separator (so there isn't a pipe after the last field on the line, even when the line doesn't have as many fields as there are elements in the sequence — see the second sample output) is trickier. The code needs to output a separator when it reads the first character of a field that should be printed after the first such field. This code achieves that:
#include <stdio.h>
#include <stdlib.h>
static const int sequence[] = { 2, 5, 7 };
static const int seqlen = 3;
static
void getFormattedOutput(char *inFile, char *outFile, char minor_sep, char major_sep)
{
FILE *ifp = fopen(inFile, "r"); // opens the file for reading
FILE *ofp = fopen(outFile, "w"); // opens the file for writing
if (ifp == NULL || ofp == NULL)
{
printf("\nFile creation is not a success, Exiting program..\n");
exit(0);
}
int c;
int seqnum = 0;
int fieldnum = 0;
int sep = 0;
while ((c = getc(ifp)) != EOF)
{
if (c == major_sep)
{
putc(major_sep, ofp);
fieldnum = 0;
seqnum = 0;
sep = 0;
}
else if (c == minor_sep)
{
if (seqnum < seqlen && fieldnum == sequence[seqnum])
seqnum++;
fieldnum++;
sep = minor_sep;
}
else if (fieldnum == sequence[seqnum])
{
if (sep != 0)
{
putc(sep, ofp);
sep = 0;
}
putc(c, ofp);
}
}
fclose(ifp);
fclose(ofp);
}
int main(void)
{
getFormattedOutput("/dev/stdin", "/dev/stdout", '|', '\n');
return 0;
}
Example run:
$ {
> echo "Afld0|Afld1|Afld2|Afld3|Afld4|Afld5|Afld6|Afld7|Afld8|Afld9"
> echo "Bfld0|Bfld1|Bfld2|Bfld3|Bfld4|Bfld5|Bfld6|Bfld7|Bfld8|Bfld9"
> echo "Cfld0|Cfld1|Cfld2|Cfld3|Cfld4|Cfld5|Cfld6|Cfld7|Cfld8|Cfld9"
> echo "Dfld0|Dfld1|Dfld2|Dfld3|Dfld4|Dfld5|Dfld6|Dfld7|Dfld8|Dfld9"
> echo "Efld0|Efld1|Efld2|Efld3|Efld4|Efld5|Efld6|Efld7|Efld8|Efld9"
> } | ./split
|Afld2|Afld5|Afld7
|Bfld2|Bfld5|Bfld7
|Cfld2|Cfld5|Cfld7
|Dfld2|Dfld5|Dfld7
|Efld2|Efld5|Efld7
$
I need to read in a file that contains text, and then a double for that text. It is simply to get the mean and standard deviation for the set of numbers, so the text that comes before is irrelevant. For example, my input file looks a little like:
preface 7.0000
chapter_1 9.0000
chapter_2 12.0000
chapter_3 10.0000
etc..
In this case, it is finding the mean and std dev for the chapters of a book. I have the section of code below, but I'm not quite sure how to "ignore" the text, and only grab the doubles. At the moment this code prints out zeros and only exits the loop when it exceeds the array limit, which I set as a constant to 20 at the beginning of the program.
FILE *ifp;
char *mode = "r";
ifp = fopen("table.txt", mode);
double values[array_limit];
int i;
double sample;
if (ifp==NULL)
{
printf("cannot read file \n");
}
else
{
i = 0;
do
{
fscanf(ifp, "%lf", &sample);
if (!feof(ifp))
{
values[i] = sample;
printf("%.4lf \n", values[i]);
i++;
if (i>=array_limit) //prevents program from trying read past array size limit//
{
printf("No more space\n");
break;
}
}
else
{
printf("read complete\n");
printf("lines = %d\n", i);
}
}while (!feof(ifp));
fclose(ifp);
}
I think you could use fscanf(ifp, "%*[^ ] %lf", &sample) for reading from your file. The * says to ignore that particular match, the [] specifices a list of characters to match and the ^ indicates to match all characters except those in [].
Or possibly (a bit simpler) fscanf(ifp, "%*s %lf", &sample).
You have two major problems -- you're using feof which is pretty much always wrong, and you're not checking the return value of fscanf, which it what tells you whether you got a value or not (or whether you got to the eof).
So what you want is something like
while ((found = fscanf(ifp, "%lf", &values[i])) != EOF) { /* loop until eof */
if (found) {
/* got a value, so count it */
if (++i >= ARRAY_LIMIT) {
printf("no more space\n");
break;
}
} else {
/* something other than a value on input, so skip over it */
fscanf(ifp, "%*c%*[^-+.0-9]");
}
}
When reading in from a file, it's often best to use fgets to read one line at a time, then extract the parts you are interested in using sscanf:
#include <stdlib.h>
#include <stdio.h>
#define ARRAY_LIMIT 10
#define LINE_LENGTH 128
int main()
{
double values[ARRAY_LIMIT];
int i, count = 0;
double sample;
FILE *ifp = fopen("table.txt", "r");
if (ifp==NULL)
{
printf("cannot read file \n");
return 1;
}
char buff[LINE_LENGTH];
while (fgets(buff, LINE_LENGTH, ifp) != NULL)
{
if (sscanf(buff, "%*s %lf", &sample) != 1) break;
values[count++] = sample;
if (count == ARRAY_LIMIT) {
printf("No more space\n");
break;
}
}
fclose(ifp);
for (i = 0; i < count; ++i) {
printf("%d: %f\n", i, values[i]);
}
return 0;
}
fgets returns NULL if it encounters the end of the file, or if a read error has occurred. Otherwise, it reads one line of the file into the character buffer buff.
The asterisk %*s in the sscanf means that the first part of the line is discarded. The second part is written to the variable sample. I am checking the return value of sscanf, which indicates how many values have been read successfully.
The loop breaks when the end of the file is reached or the count reaches the size of the array.
so I have this file called "score.txt" with contents
NAME
20
NAME2
2
And I'm using this code but it gets an error and I have no idea on how to put the integers from the file in an array.
int main(){
FILE* file = fopen ("score.txt", "r");
int i = 0;
fscanf (file, "%d", &i);
while (!feof (file))
{
printf ("%d ", i);
fscanf (file, "%d", &i);
}
fclose (file);
system("pause");
}
I'm only self learning and i've been trying to figure this out for 2hours already
The problem with using fscanf for input where some lines will fail the format is that the file will not be advanced per iteration of the while loop, so you get stuck.
You can get a solution by using fgets to grab the data and sscanf to grab the number:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
int main(void) {
int i = 0;
int ret = 0;
char buf[50];
FILE *file = fopen("score.txt", "r");
if (file == NULL) {
fprintf(stderr,"Unable to open file\n");
exit(1);
}
while (fgets(buf,sizeof(buf),file)) {
ret = sscanf(buf,"%d",&i);
if (ret == 1) { // we expect only one match
printf("%d\n", i);
} else if (errno != 0) {
perror("sscanf:");
break;
}
}
fclose(file)
return(0);
}
This will output, for your input:
20
2
We check the output of sscanf as it tells us if the format has been matched correctly, which will only happen on the lines with integer, and not the 'NAME' lines. We also check for 'errno' which will be set to non-zero if sscanf encounters an error.
We used char buf[50]; to declare a char array with 50 slots, which fgets then uses to store the line its reading; however if the line is more than 50 chars in length it will be read in 50 char chunks by fgets, and you may not get the results you desire.
If you wish to store the integers you read into an array, you'll have to declare an array, then on each read assign a slot in that array to the value of the int you read i.e. int_array[j] = i (where j will have to change with each slot you use). I'll leave it as an exercise to implement this.
The code is supposed to read a user-inputted text file name, copy every character into a multidimensional array, then display it with standard output. It compiles, but produces unintelligible text. Am I missing something?
for (i = 0; i < BIGGEST; i++) {
for (j = 0; j < BIGGESTL; j++) {
if (fgetc(array, fp) ) != EOF)
array[i][j] = c;
else array[i][j] = '\0'
}
fclose(fp);
return 0;
}
You stop filling the array when you encounter EOF, but you print the full array out no matter what.
If the data read from the file is smaller than the input array, you will read that data in and then print that data out, plus whatever random characters were in the memory locations that you do not overwrite with data from the file.
Since the requirement seems to be to print text data, you could insert a special marker in the array (e.g. '\0') to indicate the position where you encountered EOF, and stop displaying data when you reach that marker.
You had better read each line from file
For example:
int i = 0;
while(fgets(text[i],1000,fp))
{
i++;
}
Though the question is edited and only part of the code is left in question. I am posting more than what is required for the question at the moment.
Reason being, there can be numberous improvements to originally posted full code.
In main() function:
You need to check for the argc value to be equal to 2 for your purpose and only then read in value of argv[1] . Else if program executed without the command-line-argument which is file_name in this case, invalid memory read occurs, resulting in segmentation fault if you read in argv[1].
In read_file_and_show_the contents() function:
Stop reading file if end of file is reached or maximum characters is read and store in the character array.
Below Program will help you visualize:
#include <stdio.h>
/*Max number of characters to be read/write from file*/
#define MAX_CHAR_FOR_FILE_OPERATION 1000000
int read_and_show_the_file(char *filename)
{
FILE *fp;
char text[MAX_CHAR_FOR_FILE_OPERATION];
int i;
fp = fopen(filename, "r");
if(fp == NULL)
{
printf("File Pointer is invalid\n");
return -1;
}
//Ensure array write starts from beginning
i = 0;
//Read over file contents until either EOF is reached or maximum characters is read and store in character array
while( (fgets(&text[i++],sizeof(char)+1,fp) != NULL) && (i<MAX_CHAR_FOR_FILE_OPERATION) ) ;
//Ensure array read starts from beginning
i = 0;
while((text[i] != '\0') && (i<MAX_CHAR_FOR_FILE_OPERATION) )
{
printf("%c",text[i++]);
}
fclose(fp);
return 0;
}
int main(int argc, char *argv[])
{
if(argc != 2)
{
printf("Execute the program along with file name to be read and printed. \n\
\rFormat : \"%s <file-name>\"\n",argv[0]);
return -1;
}
char *filename = argv[1];
if( (read_and_show_the_file(filename)) == 0)
{
printf("File Read and Print to stdout is successful\n");
}
return 0;
}