strange behavior with cout and strings

I was beginner to c++ working on a simple string rotation program that would take a number and a string and rotate it about that index in the string. I split the string into 2 sub-strings and then appended they in the right order, however I noticed I got some weird outputs from cout when I tried to append them in the correct order. I could print out the sub-strings separately, and in reverse order, but concatenating them in the correct order would lead to weird prints. If you could point me in the right direction or towards some reference material that would be gratefully appreciated.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
  #include "FLoad.hpp"
#include <iostream>

int main()
{
    FLoad input = FLoad("testInput.txt");
    for(int i = 1; i < input.getLineAsInt(0)[0] + 1; i++)
    {
        int flipPoint = std::stoi(input.getLine(i)[0]);
        std::string str = input.getLine(i)[1];
        std::string frontStr = " ";
        std::string endStr = " ";
        if(flipPoint < 0)
        {
            endStr = str.substr(0, str.size() + flipPoint - 1);
            frontStr = str.substr(str.size() + flipPoint -1, str.size() -1);
           
        }else{
            endStr = str.substr(0, flipPoint);
            frontStr = str.substr(flipPoint, str.size() - 1);
            
        }
        std::string newString = frontStr + endStr;
        std::cout << "B:" << frontStr << '\n';
        std::cout << "B:" << endStr << '\n';
        std::cout << "C:" << newString << '\n';
        
    }
    
    return 0;
}


output:
A:whomthebelltolls
B:for
forhomthebelltolls
A:number
B:verycomplex
verycomplex


contents of testInput.txt:
2
3 forwhomthebelltolls
-6 verycomplexnumber

header file to handle reading from the file
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#pragma once
#include <fstream>
#include <string>
#include <vector>
#include <sstream>
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>

class FLoad {
    private:

     std::string rawtext ="";
     std::vector<std::vector<std::string>> seperatedLines;

    public:
     
     std::vector<std::string> simpleSeperateLines()
     {
        int fileLength = rawtext.length();
        std::string line = "";
        std::vector<std::string> simpSepLines;
        for(int i = 0; i < fileLength; i++)
        {
            if(rawtext[i] == '\n')
            {
                simpSepLines.push_back(line);
                line = "";
            }else{
                line += rawtext[i];
            }
        }
        return simpSepLines;

     }
     std::vector<std::vector<std::string>> seperateLines(std::string rawtext){
         int fileLength = rawtext.length();
         std::vector<std::vector<std::string>> lines;
         std::vector<std::string> brokenLine;
         std::string line = "";
         for(int i = 0; i < fileLength; i++){
             if(rawtext[i] != '\n'){
                 line += rawtext[i];
             }else{
                 std::string word = "";
                 for(int i = 0; i < line.length(); i++){
                     if(line[i] != ' '){
                        word += line[i];
                        
                     }else{
                        brokenLine.push_back(word);
                        word = "";
        
                     }
                 }
                 brokenLine.push_back(word);
                 word = "";
                 lines.push_back(brokenLine);
                 line = "";
                 brokenLine.clear();

             }

         }
         return lines;
     }

     FLoad(std::string filename){

        std::ifstream testInput;
        testInput.open(filename); 
        std::stringstream strStream;
        strStream << testInput.rdbuf(); 
        rawtext = strStream.str(); 
        seperatedLines = seperateLines(rawtext);
     }
     
     std::vector<std::string> getLine(int number){
         return seperatedLines[number];
     }

     std::vector<std::vector<std::string>> getLines(){
         return seperatedLines;
     }

     int getSize()
     {
        return seperatedLines.size();
     }

     std::vector<int> getLineAsInt(int number){
         std::vector<int> outVec;
         for(int i = 0; i < seperatedLines[number].size(); i++)
         {
             outVec.push_back(std::stoi(seperatedLines[number][i]));
         }
         return outVec;
     }

     std::vector<double> getLineAsDouble(int number){
         std::vector<double> outVec;
         for(int i = 0; i < seperatedLines[number].size(); i++)
         {
             outVec.push_back(std::stod(seperatedLines[number][i]));
         }
         return outVec;
     }


     int getNumOfLines(){
         return seperatedLines.size();
     }

     
};
Last edited on
Post FLoad.hpp and testInput.txt.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main()
{
   int T;
   ifstream in( "testInput.txt" );
   in >> T;
   while( T-- )
   {
      int r;
      string str;
      in >> r >> str;
      if ( r < 0 ) r = str.size() + r;
      string A = str.substr( r ), B = str.substr( 0, r );
      cout << "A:" << A << '\n'
           << "B:" << B << '\n'
           << A << B << '\n';
   }
}


A:whomthebelltolls
B:for
whomthebelltollsfor
A:number
B:verycomplex
numberverycomplex

This code is far more complex than needed (see lastchance's code above for a more succinct method). However with only the change as below to identify the output lines:

1
2
3
4
std::string newString = frontStr + endStr;
		std::cout << "A:" << frontStr << '\n';
		std::cout << "B:" << endStr << '\n';
		std::cout << "C:" << newString << '\n';


Using VS2022 and the given text file, I get the output:


A:whomthebelltolls
B:for
C:whomthebelltollsfor
A:xnumber
B:verycomple
C:xnumberverycomple


which seems to be as required for the first one, and a off-by-1 char split for the second B. However the string append gives what is expected in both cases.

Is your text file correct? Does it have control-code characters in it? Rather than printing A and B as strings, try printing each string as it's ASCII value for each char.
Last edited on
Ok. In main() L15, 16, change to:

1
2
endStr = str.substr(0, str.size() + flipPoint);
frontStr = str.substr(str.size() + flipPoint, str.size() - 1);


This now gives the required output of:


A:whomthebelltolls
B:for
C:whomthebelltollsfor
A:number
B:verycomplex
C:numberverycomplex



PS. In the .hpp file, L6-8 should be replaced with:

1
2
#include <iostream>
#include <cctype> 


as these are C++ includes - as opposed to c ones.
Last edited on
thanks I got it working on my end, I unfortunately have a tendency to overwrite and complicate code
Topic archived. No new replies allowed.