I have a string structured such as "[first something]=[second something"]
I think sscanf would be a way to seperate them!
However, scan never reports the offset properly with %n.
The line of code is something very much like:
char data[100];
char source[] = "username=katy"
int offset=-1;
sscanf([source],"%[^=],%s%n",data,&offset)
printf("sscanf is reporting %s with an offset of %i\n"
)
but the output always looks like:
sscanf is reporting username with an offset of -1
Could someone be so kind as to clear this up for me?
(Yes, I know this leaves us prone to a buffer overflow error - that is garuneteed against a little earlier in the code...)
Your comma in the scanf format string makes no sense. Instead of "%[^=],%s%n", try "%[^=]=%s%n". You should also put field width limits on both of the strings or else you could overflow the destination buffers, and you've passed too few arguments to sscanf (only one of the strings, not the other one).
A corrected version of the code might look like:
char key[100], data[100];
char source[] = "username=katy"
int offset=-1;
sscanf(source,"%99[^=]=%99s%n",key,data,&offset)
printf("sscanf is reporting %s with an offset of %i\n", data, offset);
Related
I am trying to change a string within a loop to be able to save my images with a changing variable. Code snippet is as follows:
for (frames=1; frames<=10; frames++)
{
char* Filename = "NEWIMAGE";
int Save_Img = is_SaveImageMemEx (hCam, Filename, pMem, memID,
IS_IMG_PNG, 100);
printf("Status Save %d\n",Save_Img);
}
What I want to do is put a variable that changes with the loop counter inside Filename so my saved file changes name with every iteration.
Any help would be great.
Create a file name string with sprintf and use the %d format conversion specifier for an int:
char filename[32];
sprintf(filename, "NEWIMAGE-%d", frames);
sprintf works just like printf, but "prints" to a string instead of stdout.
If you declared frames as an unsigned int, use %u. If it is a size_t use %zu. For details see your friendly printf manual page, which will tell you how you can for example zero pad the number.
Be sure that the character array you write to is large enough to hold the longest output plus an extra '\0' character. In your particular case NEWIMAGE-10 + 1 means 11 + 1 = 12 characters is enough, but 32 is future-proof for some time.
If you want to program like a pro, look at the snprintf and asnprintf functions, which can limit or allocate the memory written to, respectively.
You can use sprintf to create a formatting string:
char Filename[50];
sprintf(Filename, "NEWIMAGE%d", frames);
I am writing an assembler for 6502 and trying to read the instructions and opcode data from a file I prepared. Using sscanf to store data and it only worked partially...
File:
ADC,Im,69,2
ADC,ZP,65,2
ADC,ZPx,75,2
ADC,Ab,6D,3
ADC,Abx,7D,3
ADC,Aby,79,3
...
Here is only part of the code related to the problem. fgets works fine. Problem line commented below. Will upload more if needed.
Code:
FILE *fp = ...
char bf[15];
char name[3];
char mode[3];
char op[2];
int bytes;
while (fgets(bf,15,fp)) {
//below is the problem line
sscanf(bf, "%3[^,],%3[^,],%2[^,],%d", name, mode, op, &bytes);
}
printf("%s,%s,%s,%d\n", name, mode, op, bytes);
Output:
ADCIm,Im,69,2
ADCZP,ZP,65,2
ADCZPx75,ZPx75,75,2
ADCAb,Ab,6D,3
ADCAbx7D,Abx7D,7D,3
...
Expected to be (just like the file format):
ADC,Im,69,2
ADC,ZP,65,2
ADC,ZPx75,75,2
ADC,Ab,6D,3
ADC,Abx7D,7D,3
...
It seems that op and bytes all work alright, but there are something wrong with the name and mode variables, even though I contained the width and delimiter in the argument.
Actually, it's not sscanf that is at fault. You have undefined behavior due to buffer overruns -- printf knows nothing about the fact that your strings are not null-terminated, and it will continue printing characters until it finds a '\0'.
To stop it from doing that, you can supply a maximum field width in the format specifier:
printf("%.3s,%.3s,%.2s,%d\n", name, mode, op, bytes);
I'm trying to read 14 digit long hexadecimal numbers from a file and then print them. My idea is to use a long long int and read the lines from the files with fscanf as if they were strings and then turn the string into a hex number using atoll. The problem is I am getting a seg value on my fscanf line according to valgrind and I have absolutely no idea why. Here is the code:
#include<stdio.h>
int main(int argc, char **argv){
if(argc != 2){
printf("error argc!= 2\n");
return 0;
}
char *fileName = argv[1];
FILE *fp = fopen( fileName, "r");
if(fp == NULL){
return 0;
}
long long int num;
char *line;
while( fscanf(fp, "%s", line) == 1 ){
num = atoll(line);
printf("%x\n", num);
}
return 0;
}
Are you sure you want to read your numbers as character strings? Why not allow the scanf do the work for you?
long long int num;
while( fscanf(fp, "%llx", &num) == 1 ){ // read a long long int in hex
printf("%llx\n", num); // print a long long int in hex
}
BTW, note the ll size specifier to %x conversion in printf - it defines the integer value will be of long long type.
Edit
Here is a simple example of two loops reading a 3-line input (with two, no and three numbers in consecutive lines) with a 'hex int' format and with a 'string' format:
http://ideone.com/ntzKEi
A call to rewind allows the second loop read the same input data.
That line variable is not initialized, so when fscanf() dereferences it you get undefined behavior.
You should use:
char line[1024];
while(fgets(line, sizeof line, fp) != NULL)
To do the loading.
If you're on C99, you might want to use uint64_t to hold the number, since that makes it clear that 14-digit hexadecimal numbers (4 * 14 = 56) will fit.
The other answers are good, but I want to clarify the actual reason for the crash you are seeing. The problem is that:
fscanf(fp, "%s", line)
... essentially means "read a string from a file, and store it in the buffer pointed at by line". In this case, your line variable hasn't been initialised, so it doesn't point anywhere. Technically, this is undefined behavior; in practice, the result will often be that you write over some arbitrary location in your process's address space; furthermore, since it will often point at an illegal address, the operating system can detect and report it as a segment violation or similar, as you are indeed seeing.
Note that fscanf with a %s conversion will not necessarily read a whole line - it reads a string delimited by whitespace. It might skip lines if they are empty and it might read multiple strings from a single line. This might not matter if you know the precise format of the input file (and it always has one value per line, for instance).
Although it appears in that case that you can probably just use an appropriate modifier to read a hexadecimal number (fscanf(fp, "%llx", &num)), rather than read a string and try to do a conversion, there are various situations where you do need to read strings and especially whole lines. There are various solutions to that problem, depending on what platform you are on. If it's a GNU system (generally including Linux) and you don't care about portability, you could use the m modifier, and change line to &line:
fscanf(fp, "%ms", &line);
This passes a pointer to line to fscanf, rather than its value (which is uninitialised), and the m causes fscanf to allocate a buffer and store its address in line. You then should free the buffer when you are done with it. Check the Glibc manual for details. The nice thing about this approach is that you do not need to know the line length beforehand.
If you are not using a GNU system or you do care about portability, use fgets instead of fscanf - this is more direct and allows you to limit the length of the line read, meaning that you won't overflow a fixed buffer - just be aware that it will read a whole line at a time, unlike fscanf, as discussed above. You should declare line as a char-array rather than a char * and choose a suitable size for it. (Note that you can also specify a "maximum field width" for fscanf, eg fscanf(fp, "%1000s", line), but you really might as well use fgets).
fprintf(fp,"IP: %d: %.*s\n",
ip,
strstr(strstr(p->data, "User-Agent:"),"\n") - strstr(p->data, "User-Agent:"),
strstr(p->data, "User-Agent: ") );
fclose(fp);
Hi All, as you can see, in the above statement, I am trying to write off just the User Agent header from a char pointer which contains the entire http packet data. The thing is, After fiddling with the string format, I came up with this %.*s format which lets me, dynamically select the number of characters to be printed to the file, and then prints them. What the code is basically doing is, first, it's printing an int, then the number of chars from the occurrence of "User-Agent:" to the very next occurrence new line character is passed, and that amount of chars are then passes starting at where the "User-Agent:" starts, from the entire packet data string. I know it's all pretty messy, but it's working fine. Except that it's not working in sprintf.
Please save all my hard word! Any help is appreciated!
char *stat;
sprintf(stat,"%.*s\0",
strstr(strstr(p->data, "User-Agent:"),"\n") - strstr(p->data, "User-Agent:"),
strstr(p->data, "User-Agent: ")) ;
You are not allocating memory for stat. Try
char *stat = malloc(MAXLEN);
snprintf(stat, MAXLEN, ...);
^ ^
When you use sprintf, you need an array of characters to write into. You're writing to an uninitialized pointer.
Try this instead:
char stat[200];
sprintf(stat, etc...
Well, you are trying to write the data into uninitialized unallocated random memory location. Now that can't possibly work.
Either do:
char stat[SUFFICIENTLY_LARGE_NUMBER];
snprintf(stat, SUFFICIENTLY_LARGE_NUMBER, ...);
or:
char *stat = malloc(SUFFICIENTLY_LARGE_NUMBER);
snprintf(stat, SUFFICIENTLY_LARGE_NUMBER, ...);
and make sure "SUFFICIENTLY_LARGE_NUMBER" is enough bytes that the string fits in and not unnecessarily huge.
PS: snprintf, because your format does not include length limits. If it does, sprintf is OK, but never ever use sprintf with unlimited %s. Your %.*s, while formally limited, is not enough, because the expression will happily return more than the size of the allocated buffer, so you need another check to avoid overruning it.
I have this snippet of the code:
char* receiveInput(){
char *s;
scanf("%s",s);
return s;
}
int main()
{
char *str = receiveInput();
int length = strlen(str);
printf("Your string is %s, length is %d\n", str, length);
return 0;
}
I receive this output:
Your string is hellàÿ", length is 11
my input was:
helloworld!
can somebody explain why, and why this style of the coding is bad, thanks in advance
Several questions have addressed what you've done wrong and how to fix it, but you also said (emphasis mine):
can somebody explain why, and why this style of the coding is bad
I think scanf is a terrible way to read input. It's inconsistent with printf, makes it easy to forget to check for errors, makes it hard to recover from errors, and is incompatable with ordinary (and easier to do correctly) read operations (like fgets and company).
First, note that the "%s" format will read only until it sees whitespace. Why whitespace? Why does "%s" print out an entire string, but reads in strings in such a limited capacity?
If you'd like to read in an entire line, as you may often be wont to do, scanf provides... with "%[^\n]". What? What is that? When did this become Perl?
But the real problem is that neither of those are safe. They both freely overflow with no bounds checking. Want bounds checking? Okay, you got it: "%10s" (and "%10[^\n]" is starting to look even worse). That will only read 9 characters, and add a terminating nul-character automatically. So that's good... for when our array size never needs to change.
What if we want to pass the size of our array as an argument to scanf? printf can do this:
char string[] = "Hello, world!";
printf("%.*s\n", sizeof string, string); // prints whole message;
printf("%.*s\n", 6, string); // prints just "Hello,"
Want to do the same thing with scanf? Here's how:
static char tmp[/*bit twiddling to get the log10 of SIZE_MAX plus a few*/];
// if we did the math right we shouldn't need to use snprintf
snprintf(tmp, sizeof tmp, "%%%us", bufsize);
scanf(tmp, buffer);
That's right - scanf doesn't support the "%.*s" variable precision printf does, so to do dynamic bounds checking with scanf we have to construct our own format string in a temporary buffer. This is all kinds of bad, and even though it's actually safe here it will look like a really bad idea to anyone just dropping in.
Meanwhile, let's look at another world. Let's look at the world of fgets. Here's how we read in a line of data with fgets:
fgets(buffer, bufsize, stdin);
Infinitely less headache, no wasted processor time converting an integer precision into a string that will only be reparsed by the library back into an integer, and all the relevant elements are sitting there on one line for us to see how they work together.
Granted, this may not read an entire line. It will only read an entire line if the line is shorter than bufsize - 1 characters. Here's how we can read an entire line:
char *readline(FILE *file)
{
size_t size = 80; // start off small
size_t curr = 0;
char *buffer = malloc(size);
while(fgets(buffer + curr, size - curr, file))
{
if(strchr(buffer + curr, '\n')) return buffer; // success
curr = size - 1;
size *= 2;
char *tmp = realloc(buffer, size);
if(tmp == NULL) /* handle error */;
buffer = tmp;
}
/* handle error */;
}
The curr variable is an optimization to prevent us from rechecking data we've already read, and is unnecessary (although useful as we read more data). We could even use the return value of strchr to strip off the ending "\n" character if you preferred.
Notice also that size_t size = 80; as a starting place is completely arbitrary. We could use 81, or 79, or 100, or add it as a user-supplied argument to the function. We could even add an int (*inc)(int) argument, and change size *= 2; to size = inc(size);, allowing the user to control how fast the array grows. These can be useful for efficiency, when reallocations get costly and boatloads of lines of data need to be read and processed.
We could write the same with scanf, but think of how many times we'd have to rewrite the format string. We could limit it to a constant increment, instead of the doubling (easily) implemented above, and never have to adjust the format string; we could give in and just store the number, do the math with as above, and use snprintf to convert it to a format string every time we reallocate so that scanf can convert it back to the same number; we could limit our growth and starting position in such a way that we can manually adjust the format string (say, just increment the digits), but this could get hairy after a while and may require recursion (!) to work cleanly.
Furthermore, it's hard to mix reading with scanf with reading with other functions. Why? Say you want to read an integer from a line, then read a string from the next line. You try this:
int i;
char buf[BUSIZE];
scanf("%i", &i);
fgets(buf, BUFSIZE, stdin);
That will read the "2" but then fgets will read an empty line because scanf didn't read the newline! Okay, take two:
...
scanf("%i\n", &i);
...
You think this eats up the newline, and it does - but it also eats up leading whitespace on the next line, because scanf can't tell the difference between newlines and other forms of whitespace. (Also, turns out you're writing a Python parser, and leading whitespace in lines is important.) To make this work, you have to call getchar or something to read in the newline and throw it away it:
...
scanf("%i", &i);
getchar();
...
Isn't that silly? What happens if you use scanf in a function, but don't call getchar because you don't know whether the next read is going to be scanf or something saner (or whether or not the next character is even going to be a newline)? Suddenly the best way to handle the situation seems to be to pick one or the other: do we use scanf exclusively and never have access to fgets-style full-control input, or do we use fgets exclusively and make it harder to perform complex parsing?
Actually, the answer is we don't. We use fgets (or non-scanf functions) exclusively, and when we need scanf-like functionality, we just call sscanf on the strings! We don't need to have scanf mucking up our filestreams unnecessarily! We can have all the precise control over our input we want and still get all the functionality of scanf formatting. And even if we couldn't, many scanf format options have near-direct corresponding functions in the standard library, like the infinitely more flexible strtol and strtod functions (and friends). Plus, i = strtoumax(str, NULL) for C99 sized integer types is a lot cleaner looking than scanf("%" SCNuMAX, &i);, and a lot safer (we can use that strtoumax line unchanged for smaller types and let the implicit conversion handle the extra bits, but with scanf we have to make a temporary uintmax_t to read into).
The moral of this story: avoid scanf. If you need the formatting it provides, and don't want to (or can't) do it (more efficiently) yourself, use fgets / sscanf.
scanf doesn't allocate memory for you.
You need to allocate memory for the variable passed to scanf.
You could do like this:
char* receiveInput(){
char *s = (char*) malloc( 100 );
scanf("%s",s);
return s;
}
But warning:
the function that calls receiveInput will take the ownership of the returned memory: you'll have to free(str) after you print it in main. (Giving the ownership away in this way is usually not considered a good practice).
An easy fix is getting the allocated memory as a parameter.
if the input string is longer than 99 (in my case) your program will suffer of buffer overflow (which is what it's already happening).
An easy fix is to pass to scanf the length of your buffer:
scanf("%99s",s);
A fixed code could be like this:
// s must be of at least 100 chars!!!
char* receiveInput( char *s ){
scanf("%99s",s);
return s;
}
int main()
{
char str[100];
receiveInput( str );
int length = strlen(str);
printf("Your string is %s, length is %d\n", str, length);
return 0;
}
You have to first allocate memory to your s object in your receiveInput() method. Such as:
s = (char *)calloc(50, sizeof(char));