double a[5];
for(int i = 0; i < 5; ++i){
read(fd, &a[i], sizeof(double));
}
When I print the content of the array, it shows me only zeros. How can I read double numbers from a text file without using fscanf?
File.txt
2.00 5.11 6.90 3.4 8.7
If I read char by char until the end of line, everything is fine.
As suggested by others if you don't want to use fscanf() then probably you should read all data from file using read() and store into char buffer and parse upto whitespace and then use strtod() to convert resultant string into double.
Here is the helping solution not complete one
int main() {
int fd = open("input.txt",O_RDWR | 0664);
if(fd == -1) {
perror("open");
return 0;
}
/* first find the size of file */
int size = lseek(fd,0,2);
printf("size of file : %d \n",size);
lseek(fd,0,0);/* again start reading from beginning */
/* take buffer equal to size of file */
char *buf = malloc(size * sizeof(char) + 1);
/* read all at a time using read()*/
read(fd,buf,size);
buf[size] = '\0';
printf("%s\n",buf);
/* now parse using strtod() */
double res;
char new_buf[64]; /* to store each double number read from fil
e */
for(int iter = 0,inner_iter = 0;buf[iter] != '\0' ;iter++ ) {
if(buf[inner_iter]!=' ' ) {
new_buf[inner_iter++] = buf[iter];
continue;
}
else {
new_buf[inner_iter] = '\0';
res = strtod(new_buf,NULL);
printf("%lf\n",res);
inner_iter = 0; /* make this variable 0 again */
}
}
free(buf);
close(fd);
return 0;
}
Related
I am new to C, After 4 days, I finally managed to make a program that read a file and remove space from it. I need to also make it parallel using MPI in any way. I tried various solutions, but MPI does not seem straightforward, it is complex, can someone please help me a bit to move forward.
Here is my code. It first reads a text file, and then removes space and new line characters.
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
FILE* pInputFile;
int chr = 0;
int main()
{
FILE* fptr;
char c;
char filename[] = "Lorem.txt";
char* str, * strblank;
int i = 0;
errno_t err;
if ((err = fopen_s(&pInputFile, filename, "r")) == 0)
{
/*count the number of characters in file for file initialization*/
size_t pos = ftell(pInputFile); // Current position
fseek(pInputFile, 0, SEEK_END); // Go to end
size_t length = ftell(pInputFile); // read the position which is the size
fseek(pInputFile, pos, SEEK_SET); // restore original position
//creating dynamic array of file size
str = malloc(length * sizeof(char));
strblank = malloc(length * sizeof(char));
while ((chr = getc(pInputFile)) != EOF)
{
str[i] = chr;
i++;
}
i = 0;
printf("%s", str);
removespace(str, strblank);
printf("%s", strblank);
fclose(pInputFile);
}
else
{
fprintf(stderr, "Cannot open file, error %d\n", err);
}
return 0;
}
int removespace(char aj[500], char mj[500])
{
int i = 0, j = 0, len;
len = strlen(aj); // len stores the length of the input string
while (aj[i] != '\0') // till string doesn't terminate
{
if (aj[i] != ' ' && aj[i] != '\n') // if the char is not a white space
{
/*
incrementing index j only when
the char is not space
*/
mj[j++] = aj[i];
}
/*
i is the index of the actual string and
is incremented irrespective of the spaces
*/
i++;
}
mj[j] = '\0';
printf("\n\nThe string after removing all the spaces is: ");
return 0;
}
I would like to be able to read from a file one character at a time using read. I cannot use fgetc. I tried looking for EOF and I can't get it to work. Thanks for your help.
char data[1024];
int infile = open(inFileName, O_RDONLY);
if(infile < 0 ) return 1;
int *c = '\0';
int i = 0;
for(i =0; i<30;++i){
read(infile, &c, 1);
printf("%c\n", c);
if(c == EOF){
break;
}
}
read does not return EOF if there is no more input. read normally returns the number of bytes read. Since you are intending to read only one byte, you expect read to return 1. When it returns 0, it means it has reached the end. If it returns -1, it means it encountered an error, and you should check errno for more information.
Your program has other issues. Your use of int *c is completely wrong. Since data is already defined, you can use that to read the file, even if you only intend to use only the first byte of the buffer. You should check to see if input was actually obtained before attempting to print it.
char data[1024];
int infile = open(inFileName, O_RDONLY);
if(infile < 0 ) {
perror(inFileName);
return 1;
}
int i = 0;
for(i =0; i<30;++i){
int r = read(infile, data, 1);
if(r <= 0){
if (r < 0) perror("read");
break;
}
printf("%c\n", data[0]);
}
I need to convert a text file of the following format to binary file.
The input file only contains characters A, B, C or D. 'A' changes to '00','B' changes to '01', C changes to '10', D changes to '11'.
Sample input file:
ABBCDA
BBAABCD
BACBB
Sample output file:
000101101100
01010000011011
0100100101
I have wrote the following code, but it doesn't work.
int main()
{
FILE * fop;
FILE * fout;
int length=0;
int i;
char buffer[1000];
fop = fopen("filename.txt","r");
fout = fopen("filename.bin", "wb");
while(!feof(fop))
{
fgets(buffer,1000,fop);
length = strlen(buffer)-1;
for(i=0; i<length; i++)
{
if(buffer[i]=='A')
strcpy(buffer[i],'00');
if(buffer[i]=='B')
strcpy(buffer[i],'01');
if(buffer[i]=='C')
strcpy(buffer[i],'10');
if(buffer[i]=='D')
strcpy(buffer[i],'11');
}
fwrite(buffer, 1, sizeof(char)*length, fout);
fwrite("\n",1,sizeof(char),fout);
}
fclose(fop);
fclose(fout);
return 0;
}
What's wrong? How to solve it? Thank you.
This is the part to be fixed
while(fgets(buffer,1000,fop))
{
length = strlen(buffer)-1;
char sout[3];
for(i=0; i<length; i++)
{
*sout = '\0';
if(buffer[i]=='A')
strcpy(sout,"00");
if(buffer[i]=='B')
strcpy(sout,"01");
if(buffer[i]=='C')
strcpy(sout,"10");
if(buffer[i]=='D')
strcpy(sout,"11");
fwrite(sout, 1, strlen(sout), fout);
}
fwrite("\n",1,sizeof(char),fout);
}
Notes
the fgets within the while condition
sout to store temporarily the 2-bits (as string)
fwrite writes to sout (does not overwrite buffer), and is integrated within the for loop while the writing of \n is outside.
Version to write actual bytes (in binary) ...
while(fgets(buffer,1000,fop))
{
length = strlen(buffer)-1;
for(i=0; i<length; i++)
{
unsigned char byte = 0;
if(buffer[i]=='A')
byte = 0x0;
if(buffer[i]=='B')
byte = 0x1;
if(buffer[i]=='C')
byte = 0x2;
if(buffer[i]=='D')
byte = 0x3;
fwrite(&byte, 1, 1, fout);
}
// no more : fwrite("\n",1,sizeof(char),fout);
}
Using 0x notation to show I'm dealing with binary stuff...
And version David C. Rankin (perfectionist!)
while (fgets (buf, MAXC, fop)) { /* read each line */
char *p = buf; /* pointer to buf */
while (*p) { /* while not '\0' */
uint8_t byte = 0; /* declare byte */
if ('A' <= *p && *p <= 'Z') /* if char is A-Z */
byte = *p - 'A'; /* encode 0 - 25 */
else
byte = *p; /* write char as is */
if (fwrite (&byte, 1, 1, fout) != 1) { /* validate write */
fprintf (stderr, "error: write of '%c' failed.\n", *p);
goto badwrite; /* jump out of loops on fail */
}
p++; /* increment pointer */
}
}
badwrite:;
fclose (fop); /* close input file */
if (fclose (fout) == -1) /* close/validate output file */
fprintf (stderr, "error: on fout close.\n");
There is yet some stuff that can be improved, but for now ...
I've been stuck on this problem for a while.
I'm creating a program that that reads in an input file (just a plain .Txt) This input file stores variables in the following format:
x
21
% This is a comment
y
3
And so on. My goal is to read this input file (done), and then store every variable in the file into a global variable in my c program. I.e. Global variable x will have the value 21 and y will have the value 3 in my c file, whilst comments are ignored.
I've thought about this for a while and can't figure out what functions to use. Any suggestions would be appreciated, thanks.
(note that these variables will always have the same names, but the order in which they are presented will differ from input file to input file).
I would suggest you to have a struct with two fields.
struct Foo
{
char var_name;
int var_value;
};
Then you create an array of these structs, with the size of the expected variables in your input file.
struct Foo input_array[n];
Then, as you read your file, you set the struct fields...
for(int i = 0; i < n ; i++){
input_array[i].var_name = input_var_name;
input_array[i].var_value = input_var_value;
}
Afterwards you print the values, and they will already be in order.
First of all, we need the variables to read the values into:
int x, y, z /* etc */;
Now, lets make an array of pointers so that we can easily access the variables:
int *array[] = { &x, &y, &z /* etc */ };
Now, we need a FILE* to access the file:
FILE* fp;
Opening the file:
fp = fopen("filename.txt", "r"); /* 'r' for reading */
Checking if the file opened successfully:
if(fp == NULL)
{
printf("Error opening file");
exit(-1); /* Exit the program */
}
Now, reading the file using fscanf:
int counter = 0; /* For keeping track of the array index */
for(;;) { /* Infinite loop */
int retVal = fscanf(fp, "%d", array[counter]); /* Capture return value of fscanf */
if(retVal == 1) /* Successfully scanned a number */
{
counter++;
}
else if(retVal == 0) /* Failed to scan a number */
{
fscanf(fp, "%*s"); /* Discard a word from the file */
}
else /* EOF */
{
break; /* Get out of the loop */
}
}
Now, printing the scanned data:
int i;
for(i = 0; i < counter; i++)
printf("%d", *array[i]);
and finally, closing the file:
fclose(fp);
Full code, added with #Jongware's suggestions:
int x, y, z /* etc */;
int *array[] = { &x, &y, &z /* etc */ };
char line[1024];
const char *varNames[] = { "x", "y", "z" };
int tmp = -1;
FILE* fp;
fp = fopen("filename.txt", "r"); /* 'r' for reading */
if(fp == NULL)
{
printf("Error opening file");
exit(-1); /* Exit the program */
}
int counter = 0;
for(fgets(line, sizeof(line), stdin)) {
if(line[0] == '%')
continue;
else
{
tmp = -1;
for(int i = 0; i < sizeof(varNames) / sizeof(*varNames); i++)
{
if(strcmp(line, varNames[i]) == 0)
{
tmp = i;
break;
}
}
fgets(line, sizeof(line), stdin);
sscanf(line, "%d", array[tmp]);
}
}
int i;
for(i = 0; i < counter; i++)
printf("%d", *array[i]);
fclose(fp);
All the above code is untested
I'm writing a program that uses the command-line arguments to receive the name of a text file from the user. The text file is a very simple CSV file such as:
Bob's experiment,12,14,15,16
Mary's experiment,16,15,18
I just want it to print the experiment name then the average of all the numerical values. I'm attempting to do this by putting all the numbers and commas into a char array and I don't know where I've gone wrong.
This is what I have:
int main(int argc, char *argv[])
{
if(argc == 2) {
FILE *txt_file;
txt_file=fopen(argv[1], "rt");
char str[4096];
if(!txt_file) {
printf("File does not exist.\n");
return 1;
}
while(!feof(txt_file)){
char s;
s = fgetc(txt_file);
//prints experiment name
if(s != ',' && (!isdigit(s))) {
printf("%c", s);
}
if(isdigit(s) || s == ',') {
fgets(str, 4096, txt_file);
}
}
fclose(txt_file);
return 0;
}
There are a number of ways to do this, but you should tailor your input routine to the type of data you are reading from your file. Here you are reading lines of data, so you should focus on line-oriented input routines (fgets, getline, or a shoehorned scanf). The basic approach is to read a line of input from your file into a buffer and then parse the line as needed. You can do this dynamically allocating all storage needed, or you can define a maximum value that should be large enough to handle your data.
Next you will need to parse the buffer read from the file to get the experiment name and each of the values associated so that an average can be calculated. Again, there are many ways to do this, but strtol is tailor made for this purpose. It takes a pointer to the string to convert and returns an endptr to the next character that is not a number. This allows you to read a values and set pointer = endptr+1 which sets you up to read your next number.
I have put these pieces together in the example below. It is commented to help you follow along. Drop a comment if you have any additional questions:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXEXPS 256
int main (int argc, char* argv[])
{
if (argc < 2) {
fprintf (stderr, "error: insufficient input. Usage %s <filename>\n", argv[0]);
return 1;
}
char *line = NULL; /* line read from file (getline allocates if NULL) */
size_t n = 0; /* number of characters to read (0 - no limit) */
ssize_t nchr = 0; /* number of characters actually read by getline */
char *p = NULL; /* pointer to use parsing values from line */
char *lnp = NULL; /* second pointer to use parsing values from line */
char *expname[MAXEXPS] = {0}; /* array of MAXEXPS pointers for experiment names */
int expavg[MAXEXPS] = {0}; /* array of MAXEXPS ints to hold averages */
int val = 0; /* val returned by each call to strtol */
int eidx = 0; /* experiment index */
int idx = 0; /* value index */
FILE *txt_file = fopen(argv[1], "r");
if (!txt_file) {
fprintf (stderr, "error: unable to open file '%s'\n", argv[1]);
return 1;
}
while ((nchr = getline (&line, &n, txt_file)) != -1) /* read each line in file */
{
p = strchr (line, ','); /* find first ',' */
*p = 0; /* set it to null (zero) */
expname[eidx] = strdup (line); /* copy exp name to array (strdup allocates) */
lnp = ++p; /* set lnp to next char */
int sum = 0; /* reset sum to 0 */
idx = 0; /* reset idx to 0 */
while ((val = (int)strtol (lnp, &p, 10)) != 0 && lnp != p) /* read next number */
{
sum += val; /* add val to sum */
lnp = ++p; /* set lnp to next char */
idx++; /* inc idx */
}
expavg[eidx++] = (idx > 0) ? sum / idx : 0; /* calc avg for experiment */
}
fclose (txt_file);
/* print the averages of experiments */
n = 0;
printf ("\n Experiment Avg\n");
printf (" -----------------------\n");
while (expname[n])
{
printf (" %-18s %d\n", expname[n], expavg[n]);
n++;
}
printf ("\n");
/* free all allocated memory */
n = 0;
if (line)
free (line);
while (expname[n])
free (expname[n++]);
return 0;
}
output:
$ ./bin/csvavgfixed dat/csvavg.dat
Experiment Avg
-----------------------
Bob's experiment 14
Mary's experiment 16
memory allocation/free summary:
==22148== HEAP SUMMARY:
==22148== in use at exit: 0 bytes in 0 blocks
==22148== total heap usage: 4 allocs, 4 frees, 723 bytes allocated
==22148==
==22148== All heap blocks were freed -- no leaks are possible
==22148==
==22148== For counts of detected and suppressed errors, rerun with: -v
==22148== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)
I think this would do what you want.
#include <stdio.h>
int main(int argc, char* argv[])
{
int n = 0, count = 0, t = 0;
if(argc == 2) {
FILE *txt_file;
txt_file=fopen(argv[1], "rt");
char str[4096];
if(!txt_file) {
printf("File does not exist.\n");
return 1;
}
while(!feof(txt_file)){
char s;
s = fgetc(txt_file);
//prints experiment name
if(s != ',' && (!isdigit(s))) {
if(n!=0) {
printf("%d\n", n / count);
n = 0;
count = 0;
}
printf("%c", s);
}
if(s == ',') {
fscanf(txt_file, "%d", &t);
n+=t;
count++;
}
}
printf("%d\n", n / count);
fclose(txt_file);
return 0;
}
}