So I'm having this problem with substrings and converting them into integers. This will probably be an easy-fix but I'm not managing to find the answer.
So I receive this string "12-12-2012" and i want to split it, convert into integers and call the modifications methods like this:
string d = (data.substr(0,data.find("-")));
setDia(atoi(d.c_str()));
But it gives me the error mentioned in the title when I try to comvert into an integer.
EDIT:
Turns out that the string doesn't actually contain a '-' but this is really confusing since the string in the parameter results from this : to_char(s.diaInicio,'dd-mm-yyyy')
More information: I used the debugger and it's making the split correctly since the value that atoi receives is 12 (the first split). But I don't know why the VS can't convert into an integer even though the string passed is "12".
This code is not save in the sense that it fails when data does not contain a -.
Try this:
std::size_t p = data.find("-");
if(p == std::string::npos) {
// ERROR no - in string!
}
else {
std::string d = data.substr(0,p);
setDia(atoi(d.c_str()));
}
Please duplicate the problem with a very simple program. If what you say is correct, then the following program should also fail (taken from Danvil's example, and without calling the unknown (to us) setDia() function):
#include <string>
#include <cstdlib>
using namespace std;
int main()
{
string data = "12-12-2012";
std::size_t p = data.find("-");
if(p == std::string::npos) {
// ERROR no - in string!
}
else {
std::string d = data.substr(0,p);
atoi(d.c_str());
}
}
Related
[RESOLVED]
I'm reading in lines from a .txt file that stores scrambled up radio messages, not that it matters. One of the lines is called "it" and some of it's opening characters are numbers, the numbers are followed by a '/'. I'm trying to export these first few numbers into a string(called "s1") so it can be later be used as a single integer, here's the code that is supposed to do that:
for (i = 0; i < it.find('/'); i++)
{
s1[i] = it[i];
}
cout << s1;
but i get a string subscript range error message, what did i screw up?
EDIT
Issue is resolved now, thank you for helping out an absolute newbie :D My mistake was not knowing how strings work, for an actual answer from someone who understands the issue find Ben Voigt's replies. Correct code is: s1+= it[i];
You most likely attempted to assign outside of the allocated memory for s1.
Assuming it and s1 are std::string:
for (auto c : it)
{
if (c == '/')
{
break;
}
s1 += c;
}
cout << s1;
I'm assuming the line you originally have is of the type std::string.
The error message "subscript out of range" basically tells that you are trying to access a invalid position of an array, in your case, a string. This commonly happens when the number between brackets [ ] is out of range of the container.
One way to avoid this type of bug is to use iterator. By using iterators, you can traverse through the entire container without manually calling operator[].
Consider the following code for a simple idea, this would separate the part before / from the original string and save it to the new variable:
#include <iostream>
#include <string>
int main() {
std::string s = "42/fortytwo";
std::string result = "";
for (std::string::iterator it=s.begin(); it!=s.end(); ++it) {
if (*it == '/') break;
result += *it;
}
std::cout << result;
return 0;
}
Note:
To use iterators, a class must have correctly implemented * (unary operator), !=, ++, begin(), end() operators.
For a more consistence usage, a const iterator can be used.
I'm new at MFC and I need to do something which sounds extremely simple: determining if a string only contains hexadecimal characters.
For that, I browse through the string (it's a CString) and I verify all characters using the FindOneOf() method, as follows:
int iTest = CString(pszText[i]).FindOneOf((LPCWSTR)"0123456789ABCDEFabcdef");
For some bizarre reason, I always get -1 as a result.
What am I doing wrong?
P.s.1 I prefer not to use the SpanIncluding() method, I find the FindOneOf() quite readable but I don't know how to use it.
P.s.2 Also simple STL seems not to be working: I tried to work with std::isxdigit(pszText[i]) but in order to get this to work, I need to include <locale> and then this function is asking for a second parameter, next to the character I want to check, and a null-pointer is not allowed there (std::isxdigit(pszText[i], nullptr) does not work).
There are several problems in your code:
This is wrong:
int iTest = CString(pszText[i]).FindOneOf(LPCWSTR)"0123456789ABCDEFabcdef");
It should be:
int iTest = CString(pszText[i]).FindOneOf(L"0123456789ABCDEFabcdef");
The cast will simply make the compiler believe that "0123..." is a wide string but it isn't. You need to use the L prefix to indicate that the string is a wide string.
But even then your algorithm won't work because FindOneOf will simply find the first occurrence of any of the characters in the parameter.
Example:
int iTest = CString(L"Z223Zbc").FindOneOf(L"0123456789ABCDEFabcdef");
"Z223Zbc" is obviously not a hexadecimal string, but iTest will contain 1 because the first character of "Z223Zbc" being part of "0123456789ABCDEFabcdef" is '2' and that's at position 1.
iTest will only contain -1 if the string to be tested doesn't contain any hexadecimal characters as for example "xyz".
Therefore this solution is appropriate:
#include <cwctype>
...
WCHAR string[] = L"123abcX";
bool ishexstring = true; // assume the string is a hex string
for (int i = 0; ; i++)
{
WCHAR c = string[i];
if (c == 0)
break; // end of string => we exit the looop
if (!std::iswxdigit(c))
{
ishexstring = false; // c is no hex digit
break; // exit loop
}
}
This algorithm should be put into a function, but I'm leaving this as an exercise for the reader.
Solution using SpanIncluding (less efficient because we need tot construct a temporary CString):
bool ishexstring = CString(string).SpanIncluding(L"0123456789ABCDEFabcdef") == str;
I'm trying to read in a large matrix calculated from a text file for a finite element code. The matrix is spatially dependent though and thus I need to be able to conveniently organize the data. The outside source that calculated the values for the matrix was kind enough to put the following lines at the top of the text file
No. activity levels : 3
No. pitch-angles : 90
No. energies : 11
No. L-shells : 10
Which basically tell me the number of positions the matrix is known at. I want to be able to easily pick out these values because it will allow me to preallocate the size of the matrix, as well as know immediately how much I need to interpolate for values not given by this text file. I am trying to do that with the following code
#include<iostream>
#include<fstream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<vector>
using namespace std;
int main(){
string diffusionTensorFileName = "BAS_drift_averaged_chorus_kp.txt";
string sline;
int alphaSize=0;
ifstream diffusionTensorFile(diffusionTensorFileName.c_str());
while(getline(diffusionTensorFile,sline)){
if(strncmp(sline.c_str(),"No. pitch-angles : 90",sline.size()-1)==0 && sline.size()-1 != 0){
alphaSize = atoi(sline.c_str());
printf("alphaSize %d \n", alphaSize);
vector<double> alpha(alphaSize);
}
}
}
atoi of course doesn't work very well, and I can't seem to get strtod or any of those functions to work either. Any thoughts? I'm also open to this being the completely wrong way to do this and alternate suggestions on how to proceed.
I think the easiest way would be to use the scan_is method of the std::ctype facet imbued in the streams locale. Its job is to search for first character that matches a given classification and return a pointer to it. We'll take the result of that call and use std::stoi (C++11) to parse it into an integer.
std::locale loc(diffusionTensorFile.getloc());
auto& f = std::use_facet<std::ctype<char>>(loc);
while (std::getline(diffusionTensorFile, sline))
{
const char* begin = sline.front(),
end = sline.back() + 1;
const char* result;
if ((result = f.scan_is(f.digit, begin, end)) != end)
{
alphaSize = std::stoi(result);
// do something with alphaSize
}
}
Live Demo
I have the following code
std::string t = "11:05:47" (No spaces inside)
I want to check if it has an empty space in it (which it doesnt) so I am using
unsigned present = t.find(" ");
if (present!=std::string::npos)
{
//Ends up in here
}
The codes seems to think there is a blank space inside the string any suggestions on what I might be doing wrong
Here are the results
present = 4294967295
t = 11:15:36
IS there a boost library that could help me do this ? Any suggestions ?
Don't use unsigned. std::string::find returns a std::string::size_type, which is usually size_t.
std::string::size_type present = t.find(" ");
if (present!=std::string::npos) {
}
As pointed out by others, you could use C++11's auto to let the compiler deduce what the type of present should be:
auto present = t.find(" ");
I have the following code that doesn't work:
string line;
string line_sub;
size_t open_tag_start;
const string open_tag = "<image>";
const int open_len = open_tag.length() + 1;
open_tag_start = line.find(open_tag);
line_sub = line.substr(open_tag_start, open_len);
When I try to run this code, I get the following error:
terminate called after throwing an instance of 'std::out_of_range'
what(): basic_string::substr
Aborted (core dumped)
I've figured out that this error is occurring because the line.find line is returning a value of -1 to the variable open_tag_start. I can rectify the problem by hard coding a value of 0 into the variable open_tag_start, but I need this to a generic algorithm that will be able to find the tag at any point in the line, so it has to be a variable. Can anyone see what I'm doing wrong here?
Here's some more info.
My goal with this code if to extract a string line_sub from string line, which does indeed contain a string, and when I set size_t open_tag_start = 0, I am able to compile and execute the code and observe the expected output. line is not empty and my problem is that when I replace
line_sub = line.substr(open_tag_start, open_len);
with
line_sub = line.substr(0, open_len);
my problem goes away and I can compile and execute the code.
This is a short version of my program that contains only the parts that are causing the problems. Attempting to compile this code will yield the error message detailed above. The file rss.xml is the RSS feed for engadget.com http://www.engadget.com/rss.xml
#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
#include <cstring>
using namespace std;
void get_tag_contents(ifstream& rssfile, string line, string open_tag);
int main()
{
const string open_tag = "<image>";
ifstream rssfile;
rssfile.open("rss.xml");
string line;
getline(rssfile, line, '\n');
get_tag_contents(rssfile, line, open_tag);
return 0;
}
void get_tag_contents(ifstream& rssfile, string line, string open_tag)
{
const int open_len = open_tag.length() + 1;
size_t open_tag_start;
string line_sub;
open_tag_start = line.find(open_tag);
line_sub = line.substr(open_tag_start, open_len);
}
Unless you've left out some code, line is an empty string, so of course find fails. It is your expectation that is in error, not the find function—that's all!
As a side note, you don't need to compensate for '\0' when using C++ strings. Get rid of the + 1.
If the substring isn't found in the string, then the find() method will return std::string::npos, which is a size_type of value -1. When you call substr() with open_tag_start equalling -1, then this is what throws the out_of_range error.
As others have noted, you must check the return value of find() in case the search fails.
std::string line("this is <image> a test");
std::string line_sub;
const std::string open_tag = "<image>";
size_t open_tag_start = line.find(open_tag);
if (open_tag_start != std::string::npos)
{
line_sub = line.substr(open_tag_start, open_tag.length());
}
std::cout << line << "\n" << line_sub << "\n";
Well, are you sure that line contains <image> ?? One thing to consider is that <ImaGe> may be capitalized in some way. Also, i dont quite see what you're trying to do, because line_sub (given that your code works) will just return enter code here and the next character after that. What are you trying to accomplish?
Remember to sanitize your return values. If find returns -1, deal with the problem or throw an error.