c++ sscanf reading string vector - c++

thanks for the support on the previous post... i am now trying to store the vector string on another string and do a sscanf to check for a text eg. "TEXT" and if found append another text at the end of line....
any ideas???
#include <iostream>
#include <vector>
#include <string>
#include <stdio.h>
using namespace std;
int main() {
vector<string> vs;
vector<string>::iterator vsi;
string agent;
string buffer;
string line;
while (!(cin.eof())) {
getline(cin, buffer);
cout << buffer << endl;
vs.push_back(buffer);
};
vsi = vs.begin();
for (int count=1; vsi != vs.end(); vsi++,count++){
cout << "string" << count <<"="<< *vsi << endl;
line = *vsi;
sscanf(line, "%s %[^\n]",text);
//dummy code
if text=="TEXT" do this:
cout << "agent" << text << "endl";
}
else: do nothing
return 0;
}
[root#server dev]# g++ -o newcode newcode.cpp
newcode.cpp: In function ‘int main()’:
newcode.cpp:24: error: cannot convert ‘std::string’ to ‘const char*’ for argument ‘1’ to ‘int sscanf(const char*, const char*, ...)’
[root#server dev]#
UPDATE:
i used line.c_str() on sscanf and gives out this error
#include <iostream>
#include <vector>
#include <string>
#include <stdio.h>
using namespace std;
int main() {
vector<string> vs;
vector<string>::iterator vsi;
string agent;
string buffer;
string line;
while (!(cin.eof())) {
getline(cin, buffer);
cout << buffer << endl;
vs.push_back(buffer);
};
vsi = vs.begin();
for (int count=1; vsi != vs.end(); vsi++,count++){
cout << "string" << count <<"="<< *vsi << endl;
line = *vsi;
cout << "LINE:" << line.c_str() << endl;
sscanf(line.c_str(), "%s %[^\n]",agent);
/* cout << "agent" << agent << "endl"; */
}
return 0;
}
[root#server dev]# g++ -o newcode newcode.cpp
newcode.cpp: In function ‘int main()’:
newcode.cpp:25: warning: cannot pass objects of non-POD type ‘struct std::string’ through ‘...’; call will abort at runtime
[root#server dev]#
what i want to do is when a string on a particular line is detected it will append a text to the end of line and stdout...

It's not entirely clear what you are trying to do but if you want to get the right type passed into sscanf you'll need to change some things around. sscanf only deals with c strings and you've tried to pass it in a c++ string object, to fix this you might want to use line.c_str() in sscanf to get it passed in the right format.
A better approach would be to use a c++ algorithm like string::find though as this will remove the need to use sscanf.

I'm not sure of you want to do, but you should check out string::find : Cplusplus reference

Instead of using sscanf try using stringstream which work nearly the same as cin/cout.

Related

Passing C-Style string char * to function argument

I want to change the characters in a string passed by user, converted into a C-style string and passed as an argument to a function with a char * argument:
#include <string>
#include <cstring>
#include <iostream>
#include <stdlib.h>
void functoupper(char *myString)
{
int i=0;
char z;
do {
z= myString[i];
myString[i]=toupper(z);
++i;
} while(myString[i]!=0);
}
int main() {
std::string name;
std::cout << "Please, enter your full name in small caps: ";
std::getline (std::cin,name);
const char *myString = name.c_str();
std::cout << "Hello, " << functoupper(myString) << "!\n";
return 0;
}
I get error error: invalid conversion from 'const char*' to 'char*' [-fpermissive] when calling function functoupper(myString) in main().
The std::string::c_str() method returns a pointer to const char data, but your function expects a pointer to non-const char data. That is why you are getting an error.
You could use const_cast to cast away the const (but that is not really advisable):
char *myString = const_cast<char*>(name.c_str());
functoupper(myString);
std::cout << "Hello, " << name << "!\n";
You could use the non-const std::string::operator[] to access the string's underlying character data (just be careful because prior to C++11, characters were not required to be stored contiguously in memory, but most std::string implementations did):
functoupper(&name[0]);
std::cout << "Hello, " << name << "!\n";
In C++17 and later, you can use the non-const std::string::data() method instead:
functoupper(name.data());
std::cout << "Hello, " << name << "!\n";
That being said, heed this warning when using toupper():
Like all other functions from <cctype>, the behavior of std::toupper is undefined if the argument's value is neither representable as unsigned char nor equal to EOF. To use these functions safely with plain chars (or signed chars), the argument should first be converted to unsigned char ... Similarly, they should not be directly used with standard algorithms when the iterator's value type is char or signed char. Instead, convert the value to unsigned char first
With that said, try something more like this:
#include <string>
#include <iostream>
#include <cctype>
void functoupper(char *myString)
{
for (int i = 0; myString[i] != '\0'; ++i) {
unsigned char z = static_cast<unsigned char>(myString[i]);
myString[i] = static_cast<char>(std::toupper(z));
}
}
int main() {
std::string name;
std::cout << "Please, enter your full name in small caps: ";
std::getline(std::cin, name);
functoupper(&name[0]); // or name.data()
std::cout << "Hello, " << name << "!\n";
return 0;
}
That being said, you should just pass the entire std::string as-is into your function instead, and then you can manipulate it as needed, for instance with the std::transform() algorithm:
#include <string>
#include <iostream>
#include <algorithm>
#include <cctype>
void functoupper(std::string &myString)
{
std::transform(myString.begin(), myString.end(), myString.begin(),
[](unsigned char ch){ return std::toupper(ch); }
);
}
int main() {
std::string name;
std::cout << "Please, enter your full name in small caps: ";
std::getline(std::cin, name);
functoupper(name);
std::cout << "Hello, " << name << "!\n";
return 0;
}
Alternatively:
#include <string>
#include <iostream>
#include <algorithm>
#include <cctype>
std::string functoupper(std::string myString)
{
std::transform(myString.begin(), myString.end(), myString.begin(),
[](unsigned char ch){ return std::toupper(ch); }
);
return myString;
}
int main() {
std::string name;
std::cout << "Please, enter your full name in small caps: ";
std::getline(std::cin, name);
std::cout << "Hello, " << functoupper(name) << "!\n";
return 0;
}
As #Someprogrammerdude and #RemyLebeau comment, why not simply:
std::transform(std::begin(name), std::end(name), std::begin(name),
[](const unsigned char c)
{
return std::toupper(c);
});
But if you must do it via a char*, then you'll need to copy the data over first, something like:
char myString* = new char[name.size() + 1];
strcpy(myString, name.c_str());
EDIT: Thanks to the helpful comments by #RemyLebeau
Better still avoid all the memory management issues with the above by simply coping your std::string into a std::vector:
std::vector<char> myVec(std::begin(name), std::end(name));
myVec.push_back(`\0`);
and then call your char* function with:
functoupper(myVec.data());

how to read a const char* from keyboard input and perform strlen() on it?

So I have been trying for 1.30 hour to get this to work. I am new indeed, but I have searched all over the place and couldn't find an exact answer. I do not wish to do this another way, as it would take away the entire purpose of learning to code. I have to find why this thing isn't working. I tried dozens if not hunderds of syntaxes, but nothing works.
I want to read in a const char* name, than count the number of elements in it, so I thought had to be strlen(), and than output the name and the number of elements. If that works I can write the rest of the code.
#include <iostream>
using namespace std;
int main()
{
//writing your name, and counting the characters including \0
int a;
const char* name;
a = int strlen(name);
cin.getline(name);
cout << name;
cout >> a;
return 0;
}
There are a lot of problems with your code.
You are not allocating any memory for cin.getline() to read into. const char* name; is declaring an uninitialized pointer to nothing. You have to allocate memory for name before you can then read any data into it.
cin.getline() expects two input parameters (a pointer to an allocated buffer, and the max number of characters the buffer can hold), but you are only passing in one value.
You are calling strlen() before you have read anything into name (and there is a syntax error on your strlen() statement anyway).
You are passing a to std::cout using >>, but std::ostream does not implement the >> operator. You have to use << instead.
And lastly, don't use using namespace std;.
Try this instead:
#include <iostream>
#include <cstring>
int main()
{
//writing your name, and counting the characters including \0
int a;
char name[32];
std::cin.getline(name, 32);
a = std::strlen(name);
std::cout << "You entered: " << name << std::endl;
std::cout << "It is << a << " chars in length" << std::endl;
return 0;
}
Or, if you really don't like using std:: everywhere, at least use using <identifier>; instead of using namespace std;:
#include <iostream>
#include <cstring>
using std::cin;
using std::strlen;
using std::cout;
using std::endl;
int main()
{
//writing your name, and counting the characters including \0
int a;
char name[32];
cin.getline(name, 32);
a = strlen(name);
cout << "You entered: " << name << endl;
cout << "It is " << a << " chars in length" << endl;
return 0;
}
Now, that being said, the preferred solution is to use std::getline() instead of cin.getline():
#include <iostream>
#include <string>
int main()
{
int a;
std::string name;
std::getline(std::cin, name);
a = name.length();
std::cout << "You entered: " << name << std::endl;
std::cout << "It is " << a << " chars in length" << std::endl;
return 0;
}
I found a working solution, although I don't see where I had gone wrong. But this does exactly what I want using const char* and strlen() without using std::string.
Thanks for all your help, you have all pointed me to the correct direction.
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int main ()
{
const char *name;
int len;
name = "stephane";
len = strlen(name);
cout << name;
cout << len;
return(0);
}
As another user has pointed out, I think it's a good idea for you to take a few steps back and read the basics until you understand how pointers work.
A const char* is that: const. It could be used usually while doing things like this:
const char* cpName = "Stephane"; //expected not to change through the program's lifetime
char* pName = "Stephane"; //can be changed to point to something else
char *pOther = "Vada";
pName = pOther; //pName now points to the string "Vada"
cpName = pOther; //this won't compile as cpName is const

Obtain offset and size from file for storing in a map

I have a JSON file called short2.json which stores a tree in the following format:
{"id":442500001101774848, "reply":0, "children":[{"id":442501072373153792, "reply":1, "children":[{"id":442501562938966016, "reply":1, "children":[{"id":442502567265062912, "reply":1, "children":[]}]}]}]}
{"id":442500000258342912, "reply":0, "children":[{"id":442500636668489728, "reply":0, "children":[]}]}
I need to store the root of each tree in a hashmap along with a tuple for offset and byte-size of the line corresponding to the tree so that I can eventually do some search and copy the line from the exact location in the file into another file. For this, I will be needing the offset of every line in the file and the size of the line (or is there a better approach?)
I did the following:
#include <iostream>
#include <fstream>
using namespace std;
int main() {
ifstream files("short2.json");
string f;
while (getline(files, f)) {
fpos_t pos;
fgetpos(files, &pos);
cout << *pos << " " << sizeof(f) << endl;
}
}
However on compiling, I get the following error:
readFile.cpp: In function âint main()â:
readFile.cpp:9:22: error: invalid conversion from âvoid*â to âFILE* {aka _IO_FILE*}â [-fpermissive]
/usr/include/stdio.h:795:12: error: initializing argument 1 of âint fgetpos(FILE*, fpos_t*)â [-fpermissive]
readFile.cpp:10:12: error: no match for âoperator*â in â*posâ
How to fix this?
Thanks #LightnessRacesinOrbit for the pointers. Following is the code that I have come up with.
#include <iostream>
#include <fstream>
using namespace std;
int main() {
ifstream files("short2.json");
string f;
while (getline(files, f)) {
cout << files.tellg() - f.size() - 1 << " " << f.size() << endl;
}
}

C++ - Gettings size from vector in FOR loop

I have a loop that asks for user input, and adds it too a vector, then when if they type "EXIT" it will stop and display the list. What I am trying to do now is determine the number of elements with size()
This is what I have:
#include <iostream>
#include <string>
#include <unistd.h>
#include <iterator>
#include <vector>
using namespace std;
int main()
{
write(1,"\E[H\E[2J",7);
vector<string> list;
cout << "Enter UIDs: \n\n";
for(string uid ; cin >> uid && uid != "EXIT"; list.push_back(uid))
cout << " \n";
copy(list.begin(), list.end(), ostream_iterator<string>(cout, "\n\n"));
cout << "Vector size: " << uid.size() << endl;
return 0;
}
When attempting to compile that I get the error:
g++ sof.cpp -o sof
sof.cpp: In function ‘int main()’:
sof.cpp:16:32: error: name lookup of ‘uid’ changed for ISO ‘for’ scoping
sof.cpp:13:16: error: cannot use obsolete binding at ‘uid’ because it has a destructor
You're querying uid.size() instead of list.size()

Why is writing a std::string to cout causing an unknown operator << error?

I am getting an error when I try to output the return value from one of my methods:
Error: No operator "<<" matches these operands. Operand types are: std::ostream << std::string
Main.cpp
#include <iostream>
using namespace std;
#include "Book.h"
int main()
{
book.setTitle("Advanced C++ Programming");
book.setAuthorName("Linda", "Smith");
book.setPublisher("Microsoft Press", "One Microsoft Way", "Redmond");
book.setPrice(49.99);
cout << book.getBookInfo(); // <-= this won't compile because of the error above.
int i;
cin >> i;
return 0;
};
Method which should return string:
string Book::getBookInfo()
{
stringstream ss;
ss << title << endl << convertDoubleToString(price) << endl;
return ss.str();
}
#include <string> is missing.
How did the code get the definition of string? The header <string> also declares the stream inserter.