46

I want to make a program that will read some number in string format and output it like this: if the number is 12345 it should then output 12 23 34 45 . I tried using the substr() function from the c++ string library, but it gives me strange results - it outputs 1 23 345 45 instead of the expected result. Why ?

#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
int main(void)
{
    string a;
    cin >> a;
    string b;
    int c;

    for(int i=0;i<a.size()-1;++i)
    {
        b = a.substr(i,i+1);
        c = atoi(b.c_str());
        cout << c << " ";
    }
    cout << endl;
    return 0;
}
IAbstract
  • 19,551
  • 15
  • 98
  • 146
VaioIsBorn
  • 7,683
  • 9
  • 31
  • 28

8 Answers8

73

If I am correct, the second parameter of substr() should be the length of the substring. How about

b = a.substr(i,2);

?

Ghislain Fourny
  • 6,971
  • 1
  • 30
  • 37
26

As shown here, the second argument to substr is the length, not the ending position:

string substr ( size_t pos = 0, size_t n = npos ) const;

Generate substring

Returns a string object with its contents initialized to a substring of the current object. This substring is the character sequence that starts at character position pos and has a length of n characters.

Your line b = a.substr(i,i+1); will generate, for values of i:

substr(0,1) = 1
substr(1,2) = 23
substr(2,3) = 345
substr(3,4) = 45  (since your string stops there).

What you need is b = a.substr(i,2);

You should also be aware that your output will look funny for a number like 12045. You'll get 12 20 4 45 due to the fact that you're using atoi() on the string section and outputting that integer. You might want to try just outputing the string itself which will be two characters long:

b = a.substr(i,2);
cout << b << " ";

In fact, the entire thing could be more simply written as:

#include <iostream>
#include <string>
using namespace std;
int main(void) {
    string a;
    cin >> a;
    for (int i = 0; i < a.size() - 1; i++)
        cout << a.substr(i,2) << " ";
    cout << endl;
    return 0;
}
Community
  • 1
  • 1
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
3

substr(i,j) means that you start from the index i (assuming the first index to be 0) and take next j chars. It does not mean going up to the index j.

colombien
  • 149
  • 6
3

Another interesting variant question can be:

How would you make "12345" as "12 23 34 45" without using another string?

Will following do?

    for(int i=0; i < a.size()-1; ++i)
    {
        //b = a.substr(i, 2);
        c = atoi((a.substr(i, 2)).c_str());
        cout << c << " ";
    }
Rajendra Uppal
  • 19,218
  • 15
  • 59
  • 57
2

You can get the above output using following code in c

#include<stdio.h>
#include<conio.h>
#include<string.h>
int main()
{
  char *str;
  clrscr();
  printf("\n Enter the string");
  gets(str);
  for(int i=0;i<strlen(str)-1;i++)
  {
    for(int j=i;j<=i+1;j++)
      printf("%c",str[j]);
    printf("\t");
  }
  getch();
  return 0;
}
CharlesB
  • 86,532
  • 28
  • 194
  • 218
2

Possible solution without using substr()

#include<iostream>
#include<string>

using namespace std;


int main() {
    string c="12345";
    int p=0;

    for(int i=0;i<c.length();i++) {
        cout<<c[i];
        p++;

        if (p % 2 == 0 && i != c.length()-1) {
            cout<<" "<<c[i];
            p++;
        }
    }
}
Jesse
  • 8,605
  • 7
  • 47
  • 57
lionelmessi
  • 1,116
  • 2
  • 10
  • 17
1

The string constructor can be used to get a copy of a substring.

string(const string& str, size_t pos, size_t n) 

For example...

b = string(a, i, 2); // substring of a from position i, including 2 characters

This differs from substr in that the length n cannot be omitted. I offer this only as an alternative, not as an improvement.

ThisClark
  • 14,352
  • 10
  • 69
  • 100
0

Possible solution with string_view

void do_it_with_string_view( void )
{
    std::string a { "12345" };
    for ( std::string_view v { a }; v.size() - 1; v.remove_prefix( 1 ) )
        std::cout << v.substr( 0, 2 ) << " ";
    std::cout << std::endl;
}
antb52
  • 31
  • 2
  • 6