Reading a string in C++ using scanf [duplicate] - c++

This question already has answers here:
How to scan a string using scanf with C++
(2 answers)
Closed 9 years ago.
I am trying to read a string in C++ using scanf. I tried
char cmd[40];
scanf("%s", cmd);
string str(cmd);
But this gets me a string I want to have plus some non-sense characters.

scanf with the %s specifier will store a null terminator after the input string which prevents garbage characters from getting into the string... unless your code has undefined behavior.
Your issue is likely that the input is overflowing the buffer, resulting in undefined behavior; When using the %s specifier without an appropriate buffer size scanf may write outside the bounds of the buffer. At that point you have no guarantees about how the program will behave.
Never use %s with scanf wihtout providing a buffer size:
char cmd[40];
scanf("%39s", cmd);
string str(cmd);

Related

c++ string constructed as char array [duplicate]

This question already has answers here:
I can't double characters inside string with function
(3 answers)
Closed 2 years ago.
currently learning strings, i have the following:
string s;
s[0]='a'; s[1]='b';
cout<<s;
string s; s.clear();
s+='a'; s+='b';
cout<<s;
I get empty string as output from 1st example, and the 2nd works fine. I get that the 1st is undef behavior and that we 'push' an element the second time instead of assigning a value.
Any more clarification will be appreciated
string s;
creates empty string
s[0]='a'; s[1]='b';
this is undefined behavior, since empty string have size zero, so required buffer may not exists.
It "works" since all major compilers are using Small String Optimization (SSO). In this optimization size of string object, allows to keep small string inside that object not on a heap. As a result minimum capacity of std::string is none zero (15 in gcc if I remember correctly).
cout<<s;
Now deeding on how this stream operator is implemented it can print empty string (size size of string is zero) or "ab" or "ab<some thrash>".
On gcc it prints nothing.
To fix it you can:
resize string first s.resize(2)
use push_back API

Why dont c++ strings work with scanf and printf [duplicate]

This question already has answers here:
How to read and write a STL C++ string?
(3 answers)
Closed 4 years ago.
string a;
scanf("%s",&a);
gives me an error "unhandled exception :Access violation writing location 0x000EEFFEE" when i run the program and enter the string for expression.
whereas
char a[20];
scanf("%s",a);
works fine.
Is it only because scanf and printf are inherited from C.
What methods can I use to fix the error.
Is it possible at all to make printf scanf work with c++ strings.
The reasons std::string can't be used with printf is that std::string is not a sequence of characters.
The printf function expects a sequence of characters terminated by '\0'.
For all we know the std::string class could be implemented as:
class string
{
unsigned int capacity;
unsigned int size;
char * p_char_sequence;
};
As you can see, the first two items are not characters.
Also, there are not printf format specifiers for std::string.
In summary, there is no guarantee that the first items in memory of a std::string are the characters; it could be a class or structure.
There is a mitigation, the std::string::c_str() method. This method returns a pointer to a C-Style string equivalent of the std::string contents.
Edit 1: scanf
The scanf function is more interesting. The scanf function requires a pointer to an array of characters. There is no guarantee that the first memory address in a std::string is a sequence of characters. See printf explanation above.
Also, there is no guarantee that the pointer returned by std::string::c_str() is valid for receiving characters. It could be a temporary area in memory, used only for output. Thus it can't be used for scanf.
The scanf function will write characters to the array locations until the input is terminated. This means that if you allocate space for 3 characters and the User inputs 20 characters, the scanf function will start overwriting the array and write to whatever follows it. This could trigger a system error (such as writing outside your program's area) or write to hardware addresses. This is why most references say to use fscanf where a limit or capacity can be specified.
You need to use c-strings with scanf not c++ strings. Redeclare expression as char expression[N]; where N is a large enough number of characters to store the entire word. Also you would not need the & infront of it when you pass it to scanf since arrays are converted to pointers automatically.
An even better approach would be to replace scanf with cin >> expression; And replace printf with cout << expression; that is the way to do it in c++.

C++: Safe reading from file with std::string (&str[0]) as a buffer? [duplicate]

This question already has an answer here:
Is writing to &str[0] buffer (of a std:string) well-defined behaviour in C++11?
(1 answer)
Closed 7 years ago.
I have a binary file that I'm reading from. In the file at one point, there is a known number of bytes which make up a simple ASCII string (possibly with newlines). Right now I have:
void doSomething(istream &in) {
vector<char> buf(length + 1, '\0');
in.read(&buf[0], length);
string str(&buf[0]);
}
But I realized that it would probably be faster to do
void doSomething(istream &in) {
string str(length + 1, '\0'); // +1 needed?
in.read(&str[0], length);
}
I tried looking in the standard to see if string allocation is always sequential or if it's safe doing something like this. Safe meaning, no accidental reading into (writing to) memory not part of the string. Does anyone know?
std::string allocation is always sequential, at least as of C++11. I believe prior to that it wasn't clearly defined so, but no implementations used non-sequential storage.
You do not need to explicitly add space for a null terminator in std::string.

Converting char* to int and converting back to the same char array [duplicate]

This question already has answers here:
Why do I get a segmentation fault when writing to a "char *s" initialized with a string literal, but not "char s[]"?
(19 answers)
Why can't I write to a string literal while I *can* write to a string object?
(4 answers)
Is it possible to modify a string of char in C?
(9 answers)
Closed 8 years ago.
Basically, I am trying to increment the int value of port. This should be easy but I am a little stuck.
It compile fine, but I got this error when I run it:
Access violation writing location 0x001f5834
#include "stdafx.h"
#include "iostream"
using namespace std;
#define TESTING "5002"
int main()
{
char* port = TESTING;
int portint;
sscanf ( port, "%d", &portint );
portint++;
cout << portint << endl; // it works fine up to here, it prints 5003
sprintf ( port, "%d", portint);
return 0;
}
By default, compiler treats string literals as immutable, and an attempt to modify the contents of one results in an access violation error at run time because these strings are put into code segment, and it's read only. In your case, TESTING is a string literal, you can't not change its values. Try:
char port[] = "5002";
Meanwhile, the compiler should have warning on this: when you assign a const char* type to a char* type.
MS C++ compiler has a compiler option regards this: Zc:strictStrings.
You are trying to write "5003" back into "5002". "5002" is a string literal and cannot be written to.
I'll try to find a good duplicate for this question, because it has been asked in many ways, many times.
In your usage, "5002" becomes a static array of characters and as such can not be modified. I believe K&R address this, but I don't have the book in front of me right now. Behavior would be different if you had declared an array.

What does %.*s represent on printf? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
what does ā€œ%.*sā€ mean in printf in c
I know this question has for sure been asked elsewhere, but searching "%.*s" yields nothing meaningful on SO. Could someone please explain the following line to me?
printf("%.*s", len, buffer);
It limits the output to at most len characters. The . starts the 'precision'; the * says 'use an int from the argument list to determine the precision'. Note that the 'string' (buffer) does not even have to be null terminated if it is longer than len.
All this is easily found in the manual page for printf().
There's a nice table here showing what all the different format specifiers can do for you. For your example, let's say you have a buffer and a length defined as:
char buf[] = "Hello World";
len = 5;
You can use %.*s to print a portion of the full string:
printf("%.*s", len, buffer);
This outputs Hello the first 5 (1 based) characters in this case. Note this is the same as:
printf("%.5s", buffer);