So, I am trying to build a c program to be able to read star catalogues and store them in arrays for further analysis.
Star catalogues usually come in .csv format and have a LOT of data on them, also some slots are empty and not all of them have int, double or float type data.
I want this program to be able to read "any" star catalogue (or by that matter any .csv file).
My first aproaches to construct such program met the issue that arrays must have their sizes declared, I decided to bypass this by creating a line and column counter functions, to be implemented by the main function.
int* getfield(char* line){
FILE *fp = fopen("./hipparcos.csv", "r");
int ch;
int lines=0;
do{
ch = fgetc(fp);
if( ch== '\n'){
lines++;
}
}while( ch != EOF );
printf("number of lines in the file %d\n",lines);
return lines;
}
which does work well when implemented in the main function like this getfield("\n"); so I get to see how many lines it is reading in the terminal (therefore know its counting them somehow).
What I need is to know how to store that quantity as a variable to later declare the array size and store lines in every position, and maybe after that do a line split (and separate each line into every column).
Any insights into how to proceed or a more efficient approach is appreciated.
You returns just int value, so change header of function to
int getfield(char* line){
this should not be a pointer.
Also consider possibility of not presence of '\n' at the end of the last line of the file (in this case you will have result 1 less than the number of rows).
EDIT:
If you just want to count number of lines as number of '\n' characters changed function is as follows:
int getCharCount(char chr){
FILE *fp = fopen("./hipparcos.csv", "r");
int ch;
int lines = 0;
do{
ch = fgetc(fp);
if( ch == chr){
lines++;
}
}while( ch != EOF );
fclose(fp);
return lines;
}
you can call this from main() e.g.:
printf("number of lines in the file %d\n", getCharCount('\n')); // maybe +1 needed :-)
but I understand that it is a draft of your program, so consider as an option sending file name as a parameter to your function. This make your solution more flexible.
Related
I know there are several asks already regarding this topic, but it seemed like those were either not completely answered or hard to apply to my code, so I apologize if this is a repeat.
I am having trouble with the below function in an overall I/O program that also does word and line count (those work). char* filename is pulled from the command line. In this example it is pulling from a txt file with lorum ipsum. (69 words) In theory the below function should read from filename and write it to an array. Then read that array and checks if the current character is a space ' ' and the next character is not. It currently returns 0 regardless.
int wordcount(char* filename) {
int wc=0,i=0,z=0;
char w, test[1000];
FILE *fp;
fp = fopen(filename, "r");
while (feof(fp) == 0) {
fscanf(fp, "%c", &test[i]);
i++;
}
while (z>i-1) {
if (test[z] = ' ' && test[z+1] != ' ' ) {
wc++;z++;
}
}
return wc;
}
NOTES: i know it's super inefficient to declare a 1000 char array, but I wasn't sure how else to do it. If you have any improvements or other methods to accomplish this, it would be greatly appreciated if you shared. Also, i'm aware that this currently ignores others types of whitespace, but I am just testing this first and will expand after.
Thanks for any assistance.
There is a sample function doing what you need. Some suggestions for you code, fopen() must be followed by fclose() when you no longer need the file. Always check if the pointer returned by fopen is not NULL and do nothing in that case, just return error code. The presence of new word can be safely detected by the space character followed by a non space character in that case increment world count ++wc. Use getc() to read one character from the file object and use isspace() function to check if the character is a space one. You don't need an array to store the file if no one modifies that file during the worldcount run.
int wordcount(const char* filename)
{
int wc=0;
char c;
FILE *fp;
fp = fopen(filename, "r");
if(fp == NULL)
{
return -1;
}
bool previsspace = 1;
while ((c=getc(fp)) != EOF)
{
if (isspace(c)==0 && (previsspace==1)) ++wc;
previsspace = isspace(c);
}
fclose(fp);
return wc;
};
You will need the following include files:
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
The concrete problem why you always get a result of 0 words:
while (z>i-1) {
z is never larger than i-1. Probably you meant to loop while z is smaller than i-1 instead:
while (z<i-1) {
Additionally you only increment z when you find a word. You should increment it for every character you test, no matter if it's a space or not.
i'm new programmer in c and need some help. I'm trying to read text file which contains numbers (long doubles) separated by ','. My problem is that I don't know what is the size of each line and every solution I find online assume it's size. This is a part of work I got to do and I can't use scanf/fscanf. finally I would like to have array contains the numbers (without the ','), what is the best way to do it?
Thanks a lot!
edited:
FILE *inputFile;
inputFile = fopen("C:\\Users\\studies\\C\\Exe1\\input_example.txt",
"r");
for (int c = 0; c < 7; c++) {
fscanf(inputFile, "%Lf,", ¶ms[c]);
}
any other way I tried to read just didn't go well, fgets, getchar, etc..
Divide and conquer! See if you're able to read the file correctly without storing anything. Just read and print what you read, so you can compare your output with the input file. If they match, you're on your way.
It's easier than you think to read the file. Use a char array as a temporary buffer for each number and read the file character by into the buffer. If the input is a ',' then you have read a complete number. Same goes for the newline '\n'.
// untested snippet
char buf[1024]; // Make it big
size_t i = 0;
int c;
long double d;
while ((c = fgetc(fp)) != EOF) {
if (c == ',' || c == '\n') {
buf[i] = '\0';
d = strtold(buf);
printf("%lf%c", d, c); // debugging, sanity check
i = 0;
}
else
buf[i++] = c;
}
There may be uncovered corner cases which the snippet doesn't cover, like missing newline at end of file, or silly Windows \r\n combos. Also, string to double conversion needs proper error checking. Still, the snippet should get you going.
I have a txt file with some file names and their size.
This is how I wrote the txt file:
banana //file name
3 //the size of file banana
programs
12
music
524
I have to find a keyboard entered file name and display it's size.
This is my code:
FILE *text;
text=fopen("text.txt","r");
printf("Scan the number of letters of your file name");
int n;
scanf("%d",&n);
char s[++n];
printf("Scan the file name you are looking for: ");
int i;
for(i=0;i<=n;i++)
{
scanf("%c",&s[i]);
}
int l=0;
char c[n];
char g;
while(!feof(text))
{
if(l%2==1) {fgetc(text); fgetc(text); l++;}
if(l%2==0)
{
fgets(c,n,text);
fgetc(text);
for(i=0;i<n;i++)
{
printf("%c",c[i]);
}
l++;
}
}
Obviously, it's not correct. Can you help me? I'm a little bit confuse.
Ugh! Please learn more about basic input. Your program has various flaws:
fgetc reads single characters. This can be useful at times, but obviously you want to read whole lines. fgets does this. You use it once, but it is not advisable to mix these. Decide up front which input paradigm you want to use: char-wise (fgetc), line-wise (fgets) or token-wise (fscanf).
Please don't make the user enter the number of characters in the filename. Quick, how many characters are there in MySpiffyDocument.txt? That's work that the computer should do.
Don't use feof to control yopur input. All input functions have special return values toat indicate that either the end of the file was read or that an error occurred. For fgets, this return value is NULL, for fgetc, this return value is the special constant EOF. The functions feof and ferror are useful after you have encountered the special return values for a post mortem analysis of the two end conditions.
Your inner loop, which is responsible for the core program logic, doesn't make sense at all. For example, for an odd l, increment l and then test for an even l – which will be true, because you have just incrremented an odd l. Use else in such cases. And don't place things that happen anyway in conditional blocks: Increment l once after the if/else blocks.
Here's an example implementation:
#include <stdlib.h>
#include <stdio.h>
int process(const char *filename)
{
char line[80];
char name[80];
int size;
int count = 0;
FILE *f = fopen(filename, "r");
if (f == NULL) return -1;
while (fgets(line, sizeof(line), f)) {
if (count % 2 == 0) {
if (sscanf(line, "%s", name) < 1) continue;
} else {
if (sscanf(line, "%d", &size) < 1) continue;
printf("%12d %s\n", size, name);
}
count++;
}
fclose(f);
return 0;
}
int main()
{
char line[80];
char name[80];
puts("Please enter filename:");
while (fgets(line, sizeof(line), stdin)) {
if (sscanf(line, "%s", name) == 1) {
process(name);
break;
}
}
return 0;
}
Things to note:
The program uses 80 characters a max. buffer size; that means your lines can be up to 78 characters long – line content plus new-line '\n' plus null terminator '\0'. That should be okay for many cases, but eventually the line may overflow. (So your file-name letter count has some merit, but the real solution here is to allocate memory dynamically. I won't open that can of worms now.)
The code uses a double strategy: Read lines first, then scan into these lines with sscanf, so that only the first word on each line is read.
Empty lines are skipped. Even lines that don't hold a valid number are skipped, too. This is sloppy error handling and may trip the odd/even count.
Reading stuff interactively from the keyboard isn't very easy in C. The awkward fgets/sscanf construct in main tries to handle the case when the user enters an empty line or evokes an end-of-file signal via Ctrl-D/Z. A better and easier way is to provide arguments to the command line via argc and argv.
I've moved the file reading into a separate function.
I have a program that is trying to take a text file that consists of the following and feed it to my other program.
Bruce, Wayne
Bruce, Banner
Princess, Diana
Austin, Powers
This is my C code. It is trying to get the number of lines in the file, parse the comma-separated keys and values, and put them all in a list of strings. Lastly, it is trying to iterate through the list of strings and print them out. The output of this is just Austin Powers over and over again. I'm not sure if the problem is how I'm appending the strings to the list or how I'm reading them off.
#include<stdio.h>
#include <stdlib.h>
int main(){
char* fileName = "Example.txt";
FILE *fp = fopen(fileName, "r");
char line[512];
char * keyname = (char*)(malloc(sizeof(char)*80));
char * val = (char*)(malloc(sizeof(char)*80));
int i = 0;
int ch, lines;
while(!feof(fp)){
ch = fgetc(fp);
if(ch == '\n'){ //counts how many lines there are
lines++;
}
}
rewind(fp);
char* targets[lines*2];
while (fgets(line, sizeof(line), fp)){
strtok(line,"\n");
sscanf(line, "%[^','], %[^',']%s\n", keyname, val);
targets[i] = keyname;
targets[i+1] = val;
i+=2;
}
int q = 0;
while (q!=i){
printf("%s\n", targets[q]);
q++;
}
return 0;
}
The problem is with the two lines:
targets[i] = keyname;
targets[i+1] = val;
These do not make copies of the string - they only copy the address of whatever memory they point to. So, at the end of the while loop, each pair of target elements point to the same two blocks.
To make copies of the string, you'll either have to use strdup (if provided), or implement it yourself with strlen, malloc, and strcpy.
Also, as #mch mentioned, you never initialize lines, so while it may be zero, it may also be any garbage value (which can cause char* targets[lines*2]; to fail).
First you open the file. The in the while loop, check the condition to find \n or EOF to end the loop. In the loop, if you get anything other than alphanumeric, then separate the token and store it in string array. Increment the count when you encounter \n or EOF. Better use do{}while(ch!=EOF);
Im currently learning C through random maths questions and have hit a wall. Im trying to read in 1000 digits to an array. But without specifiying the size of an array first i cant do that.
My Answer was to count how many integers there are in the file then set that as the size of the array.
However my program returns 4200396 instead of 1000 like i hoped.
Not sure whats going on.
my code: EDIT
#include <stdio.h>
#include <stdlib.h>
int main (void)
{
FILE* fp;
const char filename[] = "test.txt";
char ch;
int count = 0;
fp = fopen(filename, "r");
if( fp == NULL )
{
printf( "Cannot open file: %s\n", filename);
exit(8);
}
do
{
ch = fgetc (fp);
count++;
}while (ch != EOF);
fclose(fp);
printf("Text file contains: %d\n", count);
return EXIT_SUCCESS;
}
test.txt file:
731671765313306249192251196744265747423553491949349698352031277450632623957831801698480186947885184385861560789112949495459501737958331952853208805511
125406987471585238630507156932909632952274430435576689664895044524452316173185640309871112172238311362229893423380308135336276614282806444486645238749
303589072962904915604407723907138105158593079608667017242712188399879790879227492190169972088809377665727333001053367881220235421809751254540594752243
525849077116705560136048395864467063244157221553975369781797784617406495514929086256932197846862248283972241375657056057490261407972968652414535100474
821663704844031998900088952434506585412275886668811642717147992444292823086346567481391912316282458617866458359124566529476545682848912883142607690042
242190226710556263211111093705442175069416589604080719840385096245544436298123098787992724428490918884580156166097919133875499200524063689912560717606
0588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450
Any help would be great.
You forgot to initialize count, so it contains random garbage.
int count = 0;
(But note that with this change it's still not going to work, since %d in a scanf format means read as many digits as you find rather than read a single digit.)
Turn on your compiler's warnings (-Wall), it will tell you that you didn't initialize count, which is a problem: it could contain absolutely anything when your program starts.
So initialize it:
int count = 0;
The other problem is that the scanfs won't do what you want, at all. %d will match a series of digits (a number), not an individual digit. If you do want to do your counting like that, use %c to read individual characters.
Another approach typically used (as long as you know the file isn't being updated) is to use fseek/ftell to seek to the end of the file, get the position (wich will tell you its size), then seek back to the start.
The fastest approach though would be to use stat or fstat to get the file size information from the filesystem.
If you want number of digits thin you tave to do it char-by-char e.g:
while (isdigit(fgetc(file_decriptor))
count++;
Look up fgetc, getc and scanf in manpages, you don't seem to understand whats going on in your code.
The way C initializes values is not specified. Most of the time it's garbage. Your count variable it's not initialized, so it mostly have a huge value like 1243435, try int count = 0.