In the original code I have a line:
input = scanf("%c%c%c%c%c", &input_key[0], &input_key[1], &input_key[2], &input_key[3], &input_key[4]);
since I have to print the program out I did:
printf(" input = scanf(\"%c%c%c%c%c\", &input_key[0], &input_key[1], &input_key[2], &input_key[3], &input_key[4]);\n");
however the output came out to:
input = scanf("dd≡Ç", &input_key[0], &input_key[1], &input_key[2], &input_key[3], &input_key[4]);
How to fix this?
% is a special character in printf that is replaced by an input argument. If you want to print the % literal, you should escape it through %%.
So your code should be:
printf(" input = scanf(\"%%c%%c%%c%%c%%c\", &input_key[0], &input_key[1], &input_key[2], &input_key[3], &input_key[4]);\n");
Related
Long time, first time. I've done a ton of digging on this to no avail, so I'll get right to it...
I'm working in C for a physics research project. I am trying to read in a file of input values... each line contains 12 values of type double that are space-delimited, and the input file is 1006 lines long. Since the file input is well-known, I have elected to use fscanf() to ingest the input, perform an operation to reorder it, and then output it into another file that will be more suitable for gnuplot use. Here is the line prior to the problem line and the problem line in question:
2.250000000000000 0.500000000000000 2.668878914693362 0.081121085306632 2.668879345525446 0.081120608880718 0.081120609109235 2.668879508723290 -1.139145600698256 -0.478208465494011 -0.476544273039587 -0.184392862164658
2.250000000000000 0.550000000000000 2.723599351123168 0.076400593002322 2.723599435547186 0.076400582995125 0.076400821024960 2.723599264264542 -0.996035795911154 -0.408011755823990 -0.409827430433329 -0.178196609653836
All I am trying to do at the moment is read the file and output only what I am concerned with before adding more logic, but fscanf() is being problematic. The relevant code in question follows (debug statements included):
int readEOF = 0;
double maxThreePhaseParticleCount = 0.0;
double particlesATotal = 0.0;
double particlesBTotal = 0.0;
double rhoA1 = 0;
double rhoA2 = 0;
double rhoA3 = 0;
double rhoB1 = 0;
double rhoB2 = 0;
double rhoB3 = 0;
FILE * two_phase_coords;
char two_phase_coords_name[255];
sprintf(two_phase_coords_name,"~/threePhaseDiagram-densities-twoPhases_tcA%f_tcB%f_aA%f_aAB%f_aB%f.dat", tcA, tcB, aA, aAB, aB);
two_phase_coords = fopen(two_phase_coords_name, "r");
readEOF = fscanf(two_phase_coords, "%lf %lf %lf %lf %lf %lf %lf %lf %*lf %*lf %*lf %*lf", &particlesATotal, &particlesBTotal, &rhoA1, &rhoB1, &rhoA2, &rhoB2, &rhoA3, &rhoB3);
while (readEOF != EOF) {
readEOF = fscanf(two_phase_coords, "%lf %lf %lf %lf %lf %lf %lf %lf %*lf %*lf %*lf %*lf", &particlesATotal, &particlesBTotal, &rhoA1, &rhoB1, &rhoA2, &rhoB2, &rhoA3, &rhoB3);
printf("just read %i...\n%.15f %.15f %.15f %.15f %.15f %.15f %.15f %.15f %.15f\n", readEOF, particlesATotal, particlesBTotal, maxThreePhaseParticleCount, rhoA1, rhoB1, rhoA2, rhoB2, rhoA3, rhoB3);
}
The 6th field of the problem line (line 988 out of 1006) is where things fall on its face... instead of reading out 0.076400582995125, the value 0.000000000000000 is read instead... readEOF returns 6 instead of the expected 8, and fscanf() fails/returns EOF on the next loop iteration.
I'm baffled. Things I have tried...
Lots of Googling.
Changing from fscanf() to fgets()/sscanf()... failure occurs at exactly the same location, and the remaining 18 lines are still NOT processed.
Creating dummy input files of 1000+ carbon copies of both the line before the problem line and the problem line... processing of each file is complete and without error.
Examining the input file with a hex editor... everything before and after the problem line looks like standard/expected ASCII to me.
Reading all 12 values on each input line into separate variables (i.e. not using the ignore character in %*lf in fscanf()).
Lots of Googling.
I would appreciate any and all help... it's been a very long time since I've been a C guru. And since this is my very first SO post, apologies in advance if I've accidentally stomped on any community expectations/etiquette.
Thank you for all of your help!!
The function in question is part of a larger environment, and the call to this function was happening before the file pointer to the input file was closed (undefined behavior).
So I wrote this function in C using sscanf:
int parse_charstar(char *pointah)
{
int numbeh;
int retaahn = sscanf(pointah,"%*[^0123456789]%d",&numbeh);
printf("\n prent deeh numbeeh %d \n",numbeh);
return numbeh;
}
I want to get a number out of a string if there, for eg.
"hello 121"
number: 121
Currently using the above I'm getting garbage values, can someone help?
EDIT:
So I found something interesting today. Apparently, this is what was happening!
My code was never wrong to begin with as pointed out by luoluo and dasblinkenlight.
Problem was how I was calling the program. I'm on linux.
I was calling it as:
parse_charstar("1000");
Output:
prent deeh numbeeh -1634553883
I tried:
parse_charstar(" 1000 "); // added spaces
Output?
prent deeh numbeeh 1000
Spot on.
Now can someone tell me why this happens?
EDIT!!!
Hell with it guys, use strtol , its made for this stuff.
http://www.cplusplus.com/reference/cstdlib/strtol/
Code copied shamelessly from the above page:
#include <stdio.h> /* printf */
#include <stdlib.h> /* strtol */
int main ()
{
char szNumbers[] = "2001 60c0c0 -1101110100110100100000 0x6fffff";
char * pEnd;
long int li1, li2, li3, li4;
li1 = strtol (szNumbers,&pEnd,10);
li2 = strtol (pEnd,&pEnd,16);
li3 = strtol (pEnd,&pEnd,2);
li4 = strtol (pEnd,NULL,0);
printf ("The decimal equivalents are: %ld, %ld, %ld and %ld.\n", li1, li2, li3, li4);
return 0;
}
A more restricted version of your sscanf would be
int retaahn = sscanf(pointah,"%*[^0-9]%d%*[^0-9]",&numbeh);
Note that this doesn't change anything in your format string. I have just used 0-9 to mention the range and added a second %*[^0-9] to make things more explicit.
Currently using the above I'm getting garbage values, can someone
help?
Probably because you're not passing the right arguments to the function. Just do a
printf("pointah : %s\n",pointah);
to see what is passed or set breakpoints and debug your program.
So since my code was never wrong, it turns out my problem was how I was calling this function.
This is how I solved it:
I was calling it as:
parse_charstar("1000");
I tried:
parse_charstar(" 1000 "); // added spaces
And it worked!
Check my edit above for more!!
I have a file and I need to check if its lines are in the following format:
name: name1,name2,name3,name4 ...
(some string, followed by ":", then a single space and after that strings separated by ",").
I tried doing it with the following code:
int result =0;
do
{
result =sscanf(rest,"%[^:]: %s%s", p1,p2,p3);
if(result==3)
{
printf("invalid!");
fclose(fpointer);
return -1;
}
}while (fgets(rest ,LINE , fpointer) != NULL);
this works good for lines like: name: name1, name2 (with space between name1, and name2).
but it fails with the following line:
name : name1,name2
I want to somehow tell sscanf not to avoid this white space before the ":".
could someone see how ?
Thanks for helping!
This works for me:
result = sscanf(rest,"%[^*:]: %[^,],%s", p1, p2, p3);
Notice the * is used to consume the space (if any).
My C program just freezes right after the "zeroed" string printed to the terminal. I can't find out why...
int formattedMsgLen = strlen(msg)+strlen(from)-strlen(MSG_PRFX_ALL) + 1;
printf("formattedMsgLen = %d\n",formattedMsgLen);
char * formattedMsg = (char*)malloc(formattedMsgLen) ;
if (NULL == formattedMsg) {
perror("malloc:");
sem_post(&writeSem);
NAMES_MUTEX_UNLOCK;
exit(EXIT_FAILURE);
}
printf("cont. building msg\n");
//memset(formattedMsg, 0, formattedMsgLen);
printf("zeroed\n");
memcpy(formattedMsg, MSG_PRFX_ALL, strlen(MSG_PRFX_ALL));
printf("msg to all: %s",formattedMsg);
EDIT:
#define MSG_PRFX_ALL ("All")
Include a newline character in your last printf statement.
printf("msg to all: %s\n",formattedMsg);
This will clear the buffer.
strlen(MSG_PRFX_ALL)=3 and memcpy just copied only 3 letters without \0
add before printf
formattedMsg[strlen(MSG_PRFX_ALL)]='\0'
Try adding this line after the last printf:
fflush(stdout);
Replace
memcpy(formattedMsg, MSG_PRFX_ALL, strlen(MSG_PRFX_ALL));
with
strcpy(formattedMsg, MSG_PRFX_ALL);
I'm trying to read a line from a file, I grab a line line using fgets. I then try to use sscanf to parse it. Sometimes I'll call sscanf and find out it returns the wrong number of arguments. So then I'll try reparse the same line string. Sometimes it works, sometimes it doesn't (which is leading me to believe that the problem isn't sscanf but something else in my code). Here's an example of what I mean:
i = sscanf(line,"%d/%d/%d %d/%d/%d %d/%d/%d %d/%d/%d\n", &faceV1, &faceUV1, &faceN1, &faceV2, &faceUV2, &faceN2, &faceV3, &faceUV3, &faceN3,
&faceV4, &faceUV4, &faceN4);
if(i == 12) {
//We gotta quad...
printf("Model.c: Quads not supported\n");
} else if(sscanf(line,"%d/%d/%d %d/%d/%d %d/%d/%d\n", &faceV1, &faceUV1, &faceN1, &faceV2, &faceUV2, &faceN2, &faceV3, &faceUV3, &faceN3) == 9) {
//Doesn't do what I expect!
...
However if I get rid of i = sscanf... and the check for i == 12 and go straight to if(sscanf(line,"%d/%d/%d %d/%d/%d %d/%d/%d\n", &faceV1, &faceUV1, &faceN1, &faceV2, &faceUV2, &faceN2, &faceV3, &faceUV3, &faceN3) == 9) it will work as expected.
So back to the title of this question, can I call sccanf multiple times on the same string? Am I calling it wrong? Or should I look elsewhere in my code for the problem?
Short answer YES you can sscanf the same string multiple times.
Your problem is that having "\n" in your string does not do what you expect...
It matches ANY white-space character space, tab, \r, and not just \n.
So you need to check for the end-of-line after scanf'ing.