Related
I was trying to compile this .c script for centos or ubuntu using gcc and after getting this error tried to debug with Code Blocks but couldn't get around this same error.
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#ifdef LINUX
#include <getopt.h>
#endif
#define STRLEN 1024*64
#define FILE1 argv[optind]
#define FILE2 argv[optind+1]
#define TEMPFILE "temp.nmon"
void hint()
{
(void)printf("Hint: convert an nmon file so it can be merged with an older one\n");
(void)printf("Syntax: nmonmerge [-a] [-v] original-file extra-file\n");
(void)printf("\t[-a] append converted extra-file data to end of the original-file\n");
(void)printf("\t[-v] verbose extra details are output\n\n");
/* 12345678901234567890123456789012345678901234567890123456789012345678901234567890 */
(void)printf("Without -a the merged data is send to stdout, so redirect it (\">\") to\n");
(void)printf("\tsave the converted data.\n");
(void)printf("Note: that header lines are striped out of the 2nd file as they are already\n");
(void)printf("\tin the original file. This assumes no configuration changes like new\n");
(void)printf("\tdisks, LUNs, adapters, networks etc., which would cause header and\n");
(void)printf("\tdata column mismatches\n");
(void)printf("Note: only the timestamps (Tnnnn) and the number of snapshots are modified\n");
(void)printf("\teverything else is unchanged.\n");
(void)printf("Note: be careful as you might have \"missing\" snapshots in the time\n");
(void)printf("\tbetween the data files.\n");
(void)printf("Note: an extra line is added, starting \"AAA,note\" and the filename\n");
(void)printf("\tthis line is ignored other tools but will help in diagnosing errors\n");
(void)printf("Note: do NOT sort the nmon file before merging (sorting not needed now anyway)\n");
(void)printf("Note: nmonmerge uses a temporary file called temp.nmon\n");
(void)printf("Example: to merge three files a.nmon, b.nmon and c.nmon\n");
(void)printf("\tnmonmerge -a a.nmon b.nmon\n");
(void)printf("\tnmonmerge -a a.nmon c.nmon\n");
(void)printf("\tNow a.nmon contains all the data\n");
(void)printf("Example: to merge three files a.nmon, b.nmon and c.nmon\n");
(void)printf("\tnmonmerge a.nmon b.nmon >x.nmon\n");
(void)printf("\tnmonmerge x.nmon c.nmon >y.nmon\n");
(void)printf("\trm x.nmon\n");
(void)printf("\tNow y.nmon contains all the data\n");
exit(0);
}
int main(int argc, char ** argv)
{
FILE *readfp;
FILE *writefp;
int i,j,k,hit,number;
char string[STRLEN+1];
int lastzzzz = 0;
int verbose = 0;
int append = 0;
writefp = stdout;
while ( -1 != (i = getopt(argc, argv, "?hva" ))) {
switch (i) {
case '?':
case 'h':
hint();
case 'v':
verbose++;
break;
case 'a':
append++;
break;
}
}
if(optind +2 != argc) {
(void)printf("Error: this command expects two filenames (nmon collected data files)\n");
hint();
}
if( (readfp = fopen(FILE1,"r")) == NULL){
perror("failed to open original file for reading");
(void)printf("file: \"%s\"\n",FILE1);
exit(75);
}
if( (writefp = fopen(TEMPFILE,"w+")) == NULL){
perror("failed to open temporary file for write");
(void)printf("file: \"%s\"\n",TEMPFILE);
exit(75);
}
(void)fprintf(writefp,"AAA,note,merged file %s starts here\n",FILE1);
for(i=0;fgets(string,STRLEN,readfp)!= NULL;i++) {
if(!strncmp(string, "ZZZZ,T",6)) {
sscanf(&string[6],"%d",&lastzzzz);
}
fprintf(writefp,"%s",string);
}
if(verbose)(void)printf("First file has %d snapshots in %d lines\n", lastzzzz,i);
fclose(readfp);
if(lastzzzz == 0) {
(void)printf("File %s does not include any ZZZZ lines! - this can't be an nmon output file = stopping.\n",FILE1);
exit(33);
}
if( (readfp = fopen(FILE2,"r")) == NULL){
perror("failed to open extra data file for reading");
(void)printf("file: \"%s\"\n",FILE2);
exit(75);
}
/* wind forward to first ZZZZ line to skip header lines */
for(i=0;fgets(string,STRLEN,readfp)!= NULL;i++) {
if(!strncmp(string, "ZZZZ,T",6)) {
(void)fprintf(writefp,"AAA,note,merged file %s starts here\n",FILE2);
(void)sscanf( &string[6],"%d",&number);
(void)sprintf(&string[6],"%04d", lastzzzz + number);
string[10] = ',';
(void)fprintf(writefp,"%s",string);
break;
}
}
if(verbose)(void)printf("Skipped %d header lines in second file\n", i);
for(k=0,hit=0;fgets(string,STRLEN,readfp)!= NULL;k++) {
/* 3 for short MEM,Tnnnn and 12 for TOP,1234567,Tnnn */
for(j=3;j<12;j++) {
if(string[j ] == ',' &&
string[j+1] == 'T' &&
isdigit(string[j+2]) ) {
hit++;
/* if(verbose)(void)printf("was=%s",string); */
(void)sscanf( &string[j+2],"%d",&number);
(void)sprintf(&string[j+2],"%04d", lastzzzz + number);
string[j+6] = ',';
(void)fprintf(writefp,"%s",string);
break;
}
}
}
if(verbose)(void)printf("Out of %d lines, converted %d lines, last snapshot was %d\n", i+k,hit, lastzzzz+number);
fclose(readfp);
fclose(writefp);
if(append) {
if( (writefp = fopen(FILE1,"w")) == NULL){
perror("failed to open original file writing");
(void)printf("file: \"%s\"\n",FILE1);
exit(75);
}
if(verbose)(void)printf("Output placed back in %s\n",FILE1);
} else {
writefp = stdout;
}
if( (readfp = fopen(TEMPFILE,"r")) == NULL){
perror("failed to open temporary file for reading");
(void)printf("file: \"%s\"\n",TEMPFILE);
exit(75);
}
for(i=0;fgets(string,STRLEN,readfp)!= NULL;i++) {
if(!strncmp(string, "AAA,snapshots,",14)) {
fprintf(writefp,"AAA,snapshots,%d\n",lastzzzz+number);
}
else
fprintf(writefp,"%s",string);
}
unlink(TEMPFILE);
return 0;
}
The error is pointing to this line: if(optind +2 != argc) { and this script is to be used to merge nmon log files and was taken from here: http://nmon.sourceforge.net/pmwiki.php?n=Site.Nmonmerge
I have no prior C programming knowledge so not sure where to start, nor the error is descriptive enough to give me any clues.
Full error with warnings:
error: 'optind' undeclared (first use in this function); did you mean 'append'?|
note: each undeclared identifier is reported only once for each function it appears in|
warning: implicit declaration of function 'isdigit' [-Wimplicit-function-declaration]|
optind should be defined in unistd.h. Since you use getopt(), you need this variable to keep track of the parameter that is currently being processed.
The variable optind is the index of the next element to be processed in argv. The system initializes this value to 1. The caller can reset it to 1 to restart scanning of the same argv, or when scanning a new argument vector.
https://linux.die.net/man/3/optind
Verify that required include files are being included. You are compiling on Linux, so you can simply remove #ifdef LINUX and the corresponding #endif.
You can also open unistd.h that comes with your compiler to see if it defines optind.
I'm a little desperate because I don't know how to create a program that only reads some data (words or numbers) from an input file and then with this data writes another file but putting them in a tabulated order ...
I don't know how to make the program look in the line of the input file for example "number of sequences: 2" and to make that it takes only the data "2" to be stored in the new file ...
Please help me
I'm just starting
Thank you all
The issue you are having is not with the loop, and not with the eof.
The real issue is you have incorrect parsing logic.
Your input file is not uniformed:
Different session lines have different "MODE" in them
Number of blank lines varies from group to group
Blank lines may actually contain any number of space characters
"Number of sequences" line appears in different places in different groups
To parse such a file you need a more flexible logic that will check each input line, collect all the data needed to build an output line, and only then print it to the output file.
To do this, you can use one loop reading only one line at a time, and then testing its contents using the strncmp function.
Once you identified the type of data the line contains, save it to a variable using sscanf function.
Here is the code that will do the job:
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv) {
FILE *file_in, *file_out;
char line[200];
/* intialize these just in case we want to validate the input file */
int current_session = 0;
int current_sequences = 0;
int current_registration = 0;
/* these arrays can probably be smaller */
char chars_given[200] = { 0 };
char chars_recognized[200] = { 0 };
file_in = fopen("summary.txt", "r");
if (file_in == NULL) {
perror("Error opening input file");
return 1;
}
file_out = fopen("ordinated.txt", "w");
if (file_out == NULL) {
perror("Error opening output file");
return -1;
}
while (fgets(line, 200, file_in) != NULL) {
/* check if this is start of session using safe string comparison */
if (strncmp(line, "session", strlen("session")) == 0) {
sscanf(line, "session %d", ¤t_session);
} else if (strncmp(line, "number of sequences", strlen("number of sequences")) == 0) {
sscanf(line, "number of sequences: %d", ¤t_sequences);
} else if (strncmp(line, "registration", strlen("registration")) == 0) {
sscanf(line, "registration %d", ¤t_registration);
} else if (strncmp(line, "characters given", strlen("characters given")) == 0) {
sscanf(line, "characters given: %s", chars_given);
} else if (strncmp(line, "characters recognized", strlen("characters recognized")) == 0) {
sscanf(line, "characters recognized: %s", chars_recognized);
} else {
/* This is a line with no information (blank or separator).
Time to print results we collected, and reset the variables
for the next set of results. */
/* check we have enough information to output a line */
if (current_session > 0 && current_sequences > 0 &&
current_registration > 0 && strlen(chars_given) > 0) {
/* check if anything was recognized */
if (strlen(chars_recognized) > 0) {
fprintf(file_out, "%d %d %d %s %s\n", current_session, current_registration,
current_sequences, chars_given, chars_recognized);
} else { /* one less parameter to output if nothing was recognized */
fprintf(file_out, "%d %d %d %s\n", current_session, current_registration,
current_sequences, chars_given);
}
/* Now reset for next time. If you don't do this, the output line will repeat */
current_registration = 0;
chars_given[0] = '\0';
chars_recognized[0] = '\0';
}
}
}
/* the last block may not be printed in the loop if there is no empty line after it */
if (current_session > 0 && current_sequences > 0 &&
current_registration > 0 && strlen(chars_given) > 0) {
/* check if anything was recognized */
if (strlen(chars_recognized) > 0) {
fprintf(file_out, "%d %d %d %s %s\n", current_session, current_registration,
current_sequences, chars_given, chars_recognized);
} else { /* one less parameter to output if nothing was recognized */
fprintf(file_out, "%d %d %d %s\n", current_session, current_registration,
current_sequences, chars_given);
}
}
fclose(file_in);
fclose(file_out);
return 0;
}
This code is a bit ugly, but I tried to keep it simple.
It can be cleaned up by using structures, some flags, and moving some of the code to separate functions.
Edit: this code omits sanity checks for simplicity, and assumes the input file is not corrupt, i.e. first non empty line is always session, lines contain all the information they should, etc.
I'm trying to read two records form a file, where one is hexadecimal formated number. Well I'm newcomer to C, before when I been reading hexadecimal, generated by ftok(), I just used printf("%x", key) and it worked fine. Now when I try to read it from the file, it does not work that way.
So my code looks like this:
int countRecords(FILE *f_p) {
int tmp_key = 0;
int tmp_msgqid = 0;
int n = 0;
while (!feof(f_p)) {
if (fscanf(f_p, "%x %i", &tmp_key, &tmp_msgqid) != 2)
break;
n = n + 1;
}
return n;
}
Later on i read this value in the code like:
printf("Records: %i \n", countRecords(f_msgList));
And this compiles with no warnings. Anyway when I run the program the value of countRecords(f_msgList) is 0, when the file have a bunch of data in it:
5a0203ff 360448
850203ff 393217
110203ff 425986
EDIT:
Here is the code where the file is opened or created:
FILE *f_msgList;
f_msgList = fopen("../message_queues.list", "a");
// if file does not exist then create one and check for errors
if (f_msgList == NULL) {
FILE *f_tmp;
f_tmp = fopen("../message_queues.list", "w");
if (f_msgList == NULL) {
fprintf(stderr, "Error occurred while creating the file! \n");
exit(1);
} else
f_msgList = f_tmp;
}
Problems
You opened the file in "append" mode. which does not let you read through the file.
If you want to write and then read the file, file pointer must be reset to the starting of the file.
feof(f_p) is worst way of checking whether file pointer is at end of the file.
Solution
Open File in "read" mode by 'r' or in append+read mode 'a+'.
if you are writing in to the file. reset it using rewind(f_p); after writing.
check out this way to read through the file :
int ret, ans, key;
while ((ret = fscanf(fp, "%x %i", &key, &ans))) {
if (ret == EOF)
break;
else
printf("%x %i \n",key, ans);
}
here integer ret is :
EOF, if the pointer is reached end of file.
0, if no input matched with the variable
(greater than 0), that is, number of matched variables with the file input
I am building a fancy alarm clock with an Arduino, Mp3 player and an LED matrix to display the time and to serve as a soft wake up light. I intend to make this project accessible and open source when it's done. I want the Arduino to chose randomly an mp3 file located on the SD card and play it, until the end of the song and then chose another one until you push the stop button. But I have trouble with the random file selection:
To have something that doesn't take too much memory I thought of a way to do the selection:
The mp3 files present on the root folder of the SD are counted during initialisation using File::openNextFile() until it return the null object. ->int n_files
Select a random number between 1 and n_files. -> int rand_song
Open the rand_song file using a loop of File::openNextFile() until the wanted file is reached (might not be so efficient but it doesn't matter if it takes a couple of seconds). -->File chosen_rand
Give the name of chosen_rand.name() to musicPlayer.startPlayingFile() so the song plays.
Go back to 1) if end of song reached
So first question, do you think it makes sense to do it this way?
Then, I did a working implementation of the above algorithm missing 4th point (see Code1). But when I add the startPlaying(), a problem occurs: between two call of the function selecting the rand_song file, the position is conserved even with calling File::rewindDirectory() (see Code2).
This lead to my second question, what is the righteous way to use File, SD and File::rewindDirectory together?
I already tried a couple a thing like closing the files (because apparently only one at the time must be open) (see Code3). But always the same, it is working for the first file, but as the rewind doesn't work, it started from the middle of the folder and then hit the end of the folder.
I hope I am precise enough and that I am not missing the essential to make it work.
void setup()
{ ... intializations done before
// Count the number of files
File folder = SD.open(music_folder);
n_files = countMP3File(folder);
folder.close();
Serial.print("Number of MP3 files: "); Serial.println(n_files);
}
int countMP3File(File dir)
{
int counter = 0;
while(true)
{
File entry = dir.openNextFile();
if (! entry)
{
dir.rewindDirectory();
break;
}
Serial.println(entry.name());
if(strstr(entry.name(), extansion) != NULL)
counter++;
entry.close();
}
Serial.println("----------------");
return counter;
}
File selectFileN(int number, File dir)
{
int counter = 0;
File return_entry;
while(true)
{
File entry = dir.openNextFile();
if (! entry)
{
Serial.println("Last file reached");
dir.rewindDirectory();
break;
}
Serial.println(entry.name());
if(strstr(entry.name(), extansion) != NULL)
counter++;
if(counter==number)
{
return_entry = entry;
dir.rewindDirectory();
break;
}
entry.close();
}
return return_entry;
}
Code1 (working)
void loop()
{
int i, rand_song;
File folder = SD.open(music_folder);
File chosen_rand;
rand_song = random(0, n_files)+1;
Serial.print("Random number: "); Serial.println(rand_song);
chosen_rand = selectFileN(rand_song, folder);
if(chosen_rand)
Serial.print("Random file name: "); Serial.println(chosen_rand.name());
folder.close();
chosen_rand.close();
Serial.print("playingMusic= "); Serial.println(musicPlayer.playingMusic);
Serial.println();
Serial.println();
delay(200);
}
Code2 (not working)
void loop()
{
int i, rand_song;
File folder = SD.open(music_folder);
File chosen_rand;
rand_song = random(0, n_files)+1;
Serial.print("Random number: "); Serial.println(rand_song);
chosen_rand = selectFileN(rand_song, folder);
if(chosen_rand)
Serial.print("Random file name: "); Serial.println(chosen_rand.name());
//Added code here
if(!musicPlayer.startPlayingFile(chosen_rand.name()))
{
Serial.println("Could not open mp3 file");
}
else Serial.println("Stated playing!");
//End added code
folder.close();
chosen_rand.close();
Serial.print("playingMusic= "); Serial.println(musicPlayer.playingMusic);
Serial.println();
Serial.println();
//Added code here
delay(2000);
musicPlayer.stopPlaying();
//End added code
delay(200);
}
Code3 (not working)
void loop()
{
int i, rand_song;
File folder = SD.open(music_folder);
File chosen_rand;
rand_song = random(0, n_files)+1;
Serial.print("Random number: "); Serial.println(rand_song);
chosen_rand = selectFileN(rand_song, folder);
if(chosen_rand)
Serial.print("Random file name: "); Serial.println(chosen_rand.name());
//Added code to close file before playing it
char * namefile = (char*)malloc(15);
strcpy(namefile, chosen_rand.name());
folder.close();
chosen_rand.close();
//End added code
if(!musicPlayer.startPlayingFile(chosen_rand.name()))
{
Serial.println("Could not open mp3 file");
}
else Serial.println("Stated playing!");
free(namefile);
Serial.print("playingMusic= "); Serial.println(musicPlayer.playingMusic);
Serial.println();
Serial.println();
delay(2000);
musicPlayer.stopPlaying();
delay(200);
}
Alright, I found the problem. As only one File of the SD card should be open at a time, when the file is open by the musicPlayer, the rewindDirectory fails (I think, correct me if I am wrong, but my tests make me believe that). So the fix is quiet easy and logic, just put the rewindDirectory after the musicPlayer closed the file, so a good place to do that is just before my function that select the random file.
So here's the working loop:
void loop()
{
int i, rand_song;
File folder = SD.open(music_folder);
File random_file;
rand_song = random(0, n_files)+1;
Serial.print("Random number: "); Serial.println(rand_song);
folder.rewindDirectory();
random_file = selectFileN(rand_song, folder);
folder.close();
if(!musicPlayer.startPlayingFile(random_file.name()))
{
Serial.println("Could not open mp3 file");
}
else Serial.println("Stated playing!");
random_file.close();
Serial.print("playingMusic= "); Serial.println(musicPlayer.playingMusic);
Serial.println();
Serial.println();
delay(2000);
musicPlayer.stopPlaying();
delay(200);
}
Im taking a class in c programming and I have this project where they give us a half-made project, and we need to finish it and fix some of the functions.
This project is about sort of a social network.
In this project you can send messages to other users (on the same computer for now) by writing the target user and then you enter the message. Afterwards the message is saved in a file called "messages.txt" in the same folder in this Format:
"[At]25/08/2013 [From]user1 [To]user2 [Message]hello whats up?"
"[At]Date [From]user [To]user2 [Message]any user input"
now after writing this, i go to the second user and try to read from the file with this function:
void showUnreadMessages(char* userName) // the function gets the name of the current
user that wishes to read his/hers messages
{
char msg[MAX_MESSAGE];
char toU[MAX_USER_NAME];
char fromU[MAX_USER_NAME];
char at[15];
int count = 0, flag = 0, count1 = 0;
FILE *file = fopen(MESSAGE_FILENAME, "rt"); //open the messages file
FILE *temp;
clearScreen(); //system("CLS")
if (file == NULL) //if the file didn't exict open one
{
printf("No messages\n");
flag = 1;
_flushall();
file = fopen(MESSAGE_FILENAME, "wt");
_flushall();
}
while (!feof(file) && flag == 0) //if the file did exict
{
if (count1 == 0)
{
temp = file;
}
_flushall();
fscanf(file, "[At]%s [From]%s [To]%s [Message]%s\n", at, fromU, toU, msg); //scan one line at a time
_flushall();
if (strcmp(userName, toU) == 0) //if the userNames match than its a message for the current user
{
count++;
}
count1++;
}
fclose(file);
if (count > 0 && flag == 0) //if there are messages to user
{
printf("You have %d new Messages\n", count);
_flushall();
while (!feof(temp))
{
_flushall();
fscanf(temp, "[At]%s [From]%s [To]%s [Message]%s\n", at, fromU, toU, msg); //scan one line at a time to print it for the user
_flushall();
if (strcmp(userName, toU) == 0)
{
printf("New message at %s from: %s\nStart of message: %s\n-----------------------------------------\n", at, fromU, msg);
}
}
fclose(temp);
}
else if (count == 0 && flag == 0)
{
printf("You have no Messages\n");
}
if (!file)
{
remove(MESSAGE_FILENAME);
}
PAUSE; // system("PAUSE")
}
Now when i try to read with this function, it only shows that the message is the first word in the message section on the first line...
For example For "[At]25/08/2013 [From]user1 [To]user2 [Message]hello whats up?"
the message will be "hello"
and it will be printed twice.. i dont know what to do, for some reason when i open the file and do fscanf for one time it also shows that the pointer file starts "up?[At]... (what appears on the second line)"
Please help me if you understand what i did wrong (which i know is a lot)
Thanks in advance
This part of fscanf :
"..etc. [Message]%s\n"
will only read ONE word of "Hello what's up" because %s parses for contiguous characters.
nr_fields = fscanf(file, "[At]%s [From]%s [To]%s [Message]%80c\n"
would read up to 80 characters regardless of spaces etc. in the text message. Also, the destination for %80c must be 80 characters or more!
Also, always test for number of fields found by fscanf.
Finally, fscanf works when used as directed, but it does have some subtle aspects.
One issue is that temp is pointing to a handle that is no longer valid after you call fclose(file) after the first loop. You could use fgets() to read a line and strtok() and strncpy() to split the read string.
I think it would be a good idea to encapsulate the reading in an extra function to reduce code duplication.