Problems when I use C language "sscanf" to parse a string - c++

When I wanted to parse a string "INSERT 3 zhaoliu 13", I used sscanf, but the debugging interface on the left of vscode told me that the first digit of "name" was '00', that is, only "haoliu" was scanned, I'm guessing it's a buffer issue, but how do I fix it.
enter image description here
Below is my code
#include<iostream>
#include"string.h"
using namespace std;
int main(){
char INSERT[10];
int id;
char name[15];
short strength;
string instr = "INSERT 3 zhaoliu 13";
sscanf(instr.c_str(), "%s %d %s %d", INSERT, &id, name, &strength);
}
I tried to check a lot of information, but couldn't find a solution

You've specified the wrong type for one of your variables. strength is a short so it should correspond to %hd, not to %d.
sscanf(instr.c_str(), "%s %d %s %hd", INSERT, &id, name, &strength);
In the future, I recommend compiling with warnings turned on. With -Wall on g++, I get a warning indicating exactly this.
so_scanf2.cpp:12:51: warning: format ‘%d’ expects argument of type ‘int*’, but argument 6 has type ‘short int*’ [-Wformat=]
12 | int result = sscanf(instr.c_str(), "%s %d %s %d", INSERT, &id, name, &strength);
| ~^ ~~~~~~~~~
| | |
| int* short int*
| %hd

Related

swscanf can't read integer value

std::wifstream ifstream("JobList.txt");
ifstream.imbue(std::locale(std::locale::empty(), new std::codecvt_utf8<wchar_t>));
if (!ifstream.is_open()) {
std::cout << "파일을 찾을 수 없습니다!" << std::endl;
return 0;
}
std::wstring s;
wchar_t name[20];
int priority{};
int workingTime{};
int requestTime{};
while (ifstream) {
std::getline(ifstream, s);
swscanf(s.data(), L"%[^',']s, %d, %d, %d", name, &priority, &workingTime, &requestTime);
mRequestArrivationQueue.emplace(name, priority, workingTime, requestTime);
}
ifstream.close();
This is JobList.txt file
Good Boy, 1, 2, 5
도서 대출, 1, 2, 13
swscanf read only first wstring(name), but it doesn't read rest integer values
There is a little error in your code and a terrible (even if common) bad practice.
The error in that the conversion format specifier is [set] and it shall not be followed with a s. Here the format string requires a s character afer the first field (which is impossible) so the conversions stops after decoding the first field. The fix is trivial, remove that offending s (and the useless quotes, thanks to #AdrianMole for his comment):
swscanf(s.data(), L"%[^,], %d, %d, %d", name, &priority, &workingTime, &requestTime);
And the terrible practice is to fail to test the return value of a scanf family function. Had you tested it, you would have immediately found that it was 1 and that only the first field had been decoded.
IMHO, unless you are a C programmer and have used the C io functions for a long time, you should better use a C++ [w]stringstream. The syntax is not easier, but error detection is better...

sscanf_s access violation when seperate string and integer

char a[200] = { 0 };
char tst[20] = "aaaa 123\n";
int i;
sscanf_s(tst, "%s %d",a, &i);
printf("reasult:%s %d", a,i);
No matter I use char tst[20] = "aaaa 123\n"; or char* tst = "aaaa 123\n";,
it always shows access violation.
I need to seperate a string an integer from a string. But why this happens ?
sscanf_s expects two arguments for %c, %s and %[, the second being the size of the buffer passed. The following should work:
sscanf_s(tst, "%s %d", a, sizeof(a), &i);

sscanf error: cannot convert 'String' to 'const char*'

I'm trying to extract two numbers separated by a space from a string and save them as two ints. For example:
if input_string = "1 95" then:
servo_choice = 1
input_number = 95
Code:
String input_string = "";
int input_number = 0;
int servo_choice = 0;
input_string = Serial.readString();
sscanf( input_string, "%d %d", &servo_choice, &input_number );
The IDE gives me this error:
exit status 1
cannot convert 'String' to 'const char*' for argument '1' to 'int scanf(const char*, ...)'
Edit: I guess
input_number = input_string.substring(1,5).toInt();
Actually works and does what I want. I'd still like to know how to get sscanf to work if possible.
Thanks for any replies in advance..
You could try to convert your String into a char array with toCharArray and pass that to sscanf. Something like that (not tested though)
int buffer_len = input_string.length() + 1;
char buffer[buffer_len];
input_string.toCharArray(buffer, buffer_len);
sscanf(buffer, "%d %d", &servo_choice, &input_number);
The String is a class, not a basic type. That means that you need a method to convert / return a pointer to char if you want to use it in a sscanf. That method exists and it's called c_str() .
So, your line has to be:
sscanf( input_string.c_str(), "%d %d", &servo_choice, &input_number );

scanf_s error visual studio

int setN, setN2;
char sign;
scanf_s("do %d %c %d", &setN, &sign, &setN2);
I'm input "do 1 + 3", for example, and program in vs fall with an error "Unhandled exception at 0x650de541 in disc_II_2_1.exe: 0xC0000005: Access violation writing location 0xc96ff41e".
P.S. code below get the same result.
scanf_s("do %d %c %d", &setN, &sign, &setN2, 8);
What am I doing wrong?
From MSDN:
Unlike scanf and wscanf, scanf_s and wscanf_s require the buffer size
to be specified for all input parameters of type c, C, s, S, or string
control sets that are enclosed in []. The buffer size in characters is
passed as an additional parameter immediately following the pointer to
the buffer or variable.
and later
In the case of characters, a single character may be read as follows:
char c;
scanf_s("%c", &c, 1);
At the end of that reference, there are also a few examples where you may see that:
the count argument should appear immediately after the corresponding input
the count argument should correspond to the maximum number of expected char (or as stated above for a single char, it should be 1)
So, in your particular case you should have:
scanf_s("do %d %c %d", &setN, &sign, 1, &setN2);

don't care in scanf

Imagine the following:
you read in a string with scanf() but you only need a few of the datapoints in the string.
Is there an easy way to throw away the extraneous information, without losing the ability to check if the appropriate data is there so you can still reject malformed strings easily?
example:
const char* store = "Get: 15 beer 30 coke\n";
const char* dealer= "Get: 8 heroine 5 coke\n";
const char* scream= "Get: f* beer 10 coke\n";
I want to accept the first string, but forget about the beer because beer is yuckie.
I want to reject the second and third strings because they are clearly not the appropriate lists for the 7/11;
So I was thinking about the following construction:
char* bId = new char[16];
char* cId = new char[16];
int cokes;
sscanf([string here], "Get: %d %s %d %s\n", [don't care], bId, &cokes, cId);
This way I would keep the format checking, but what would I put for [don't care] that doesn't make the compiler whine?
Of course I could just make a variable I don't use later on, but that is not the point of this question. Also checking the left and right side seperately is an obvious solution I am not looking for here.
So, is there a way to not care about but still check the type of a piece of string in scanf and friends?
Use a * as assignment suppression character after %
Example:
sscanf([string here], "Get: %*d %s %d %s\n", bId, &cokes, cId);