namespace issue with scope

Hello,

I am a beginner at writing c++.
In the code below, I am trying to include this namespace but when I compile just the below code, I get an error telling me that some functions are out of scope.
eg:

If you are able to link a site with some info on my error, It will be much appreciated.

Thankyou

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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#include <string>
#include <iomanip>
#include <sstream>
#include <vector>
#include <cmath>
#include <iostream>

using namespace std;

enum TextFormatEnum{
FINDTITLE,
USESETTITLE
};

namespace TextFormater {

    int titleBarLength = 0;

    char titleBarChar = '~';

    string centerChar = "@";
    string justifyChar = "#";
    string wrapChar = "$";

    stringstream originalInputString("");
    stringstream outputString("");

    //this is the main function
    string processInput(string unformattedText, TextFormatEnum titleChoise)
    {
        //save input to the global
        originalInputString << unformattedText;

        string lineData = "";

        bool isToCenter = true;
        bool isToJustify = true;
        bool isToWrap = true;

        //when using, you can set the title pre function call and mention it in the second argument and then just use that hard value or you can opt for the deduction by the program (5% larger)
        if (titleChoise == FINDTITLE)
            calculateBarLength();

        appendTitleBar();

        while (getline(originalInputString, lineData))
        {
            //now we search the string for the commands

            //the int recast of the find functions will retrun -1 if the character/string is not found else it will return the index of the substr

            isToCenter = (int)lineData.find("@") + 1;
            isToCenter = (int)lineData.find("#") + 1;
            isToWrap = (int)lineData.find("#") + 1;

            //center command
            if (isToCenter)
                centerText(lineData);
            else if (isToJustify)
                justifyText(lineData);
            else if (isToWrap)
                centerTextWrapper(lineData);
        }

        appendTitleBar();
    }

    //find the bar length needed and 
    void calculateBarLength()
    {
        titleBarLength = 0;

        stringstream inputString(originalInputString.str());
        string lineData = "";

        //finding the longest line in the input string
        while (getline(inputString, lineData))
            if ((int)lineData.length() > titleBarLength)
                titleBarLength = (int)lineData.length();

        //title 5% > longest line, so:
        titleBarLength = round(titleBarLength + (titleBarLength * 0.05));
    }

    void appendTitleBar()
    {
        stringstream titleBar("");

        titleBar.fill(titleBarChar);
        titleBar.width(titleBarLength);

        outputString << titleBar.str() << "\n";

    }

    void centerText(string text2Center)
    {
        text2Center = removeCmdChar(text2Center, "@");

        int textLength = (int)text2Center.length();

        //this calculates the space needed to shift the text to center it relative to the titleBar
        int spaceToCenter = round((titleBarLength - textLength) / 2);

        putSpace(textLength, spaceToCenter);

        outputString << text2Center << "\n";
    }

    void justifyText(string text2Justify)
    {
        //example argument: "this is my left text#this is my right text"

        //-1 because the "#" character will be replaced with ""
        int textLength = (int)text2Justify.length() - 1;

        //index of the left text = 0
        int lenLeftText = text2Justify.find("#") - 1;

        //we will not add one as that character will be replaced with "" later
        int indexRightText = text2Justify.find("#");
        int lenRightText = textLength - indexRightText;

        text2Justify = removeCmdChar(text2Justify, "#");

        int space2end = floor(titleBarLength - (2 * textLength));

        //left text
        outputString << text2Justify.substr(0, lenLeftText);

        putSpace(textLength, space2end);

        //right text
        outputString << right << text2Justify.substr(indexRightText, lenRightText);
    }

    void centerTextWrapper(string text2center)
    {
        //this is centerText but with next lines on the top and bottom
        outputString << "\n";
        centerText(text2center);
        outputString << "\n";
    }

    string removeCmdChar(string lineData, string commandStr)
    {
        int indexOfCommand = lineData.find(commandStr);
        lineData.replace(indexOfCommand, 1, "");

        return lineData;
    }

    void putSpace(int textLength, int space2insert)
    {
        //this controle structure checks to prevent negative width
        if (titleBarLength > textLength)
        {
            outputString.fill(' ');
            outputString.width(space2insert);
        }
        else
            cout << "title bar too short for this operation" << endl;
    }
}
Last edited on
You are using functions before you've declared/defined them. Add forward declarations for your functions:

17
18
19
20
21
22
23
   void calculateBarLength();
   void appendTitleBar();
   void centerText(string text2Center);
   void justifyText(string text2Justify);
   void centerTextWrapper(string text2center);
   string removeCmdChar(string lineData, string commandStr);
   void putSpace(int textLength, int space2insert);

You are doing several "double to int" conversions that could lead to possible loss of data, truncating decimal values.
also L52-54 are fragile as you're making assumptions.......

Note that passing a string type by value causes a copy of the data. This can be expensive. Where possible, pass by const ref to avoid unnecessary copies.

You're also using int for a .size() when size_t should be used.
@Furry Guy
Thank you so much, I have been looking on the net for so long, nowhere did I find it as simply as you've stated. Thank you for saving me a lot of time.

@seeplus
Thank you for the note, I am just doing c++ as a university thing where our demonstrators really only care about the code working so I don't always keep best practices in mind. I will remind myself to pass by reference and use size_t instead of .size()

About lines 52 to 54, if you don't mind me asking, how are those lines no good?

I will include this explanation as the comment above it is a little bad:

the find() function with the (int) will return -1 if it cannot find the substring.
if the substring is found, it will return >=0
if we add one to the result, then we get 0 is substr is not found and >0 if found
this acts like a bool, no?

here is the comment I included in the original file for the implementation

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
/*  Commands:

    @: will center text
    #: will right justify text
    $: will wrap and center text

*/

/*  these are some instructions on how to use this namespace

    this namespace is intended for display() functions that use the stringstream stuff where, we incase the text to be displayed on one set of titleBars (see example below). 

    you can specify what parts need to be formatted with a with the abovementioned commands

    eg:

    @Welcome to this program!
    @written by Zane

    leftJustified#rightJustified 
    $wrapAndCenter
    leftJustified2

    in the above example input we need to first calculate the len of the title bar 
    "~" thing and then format the console text accordingly using iomanip functions
    we need to use the namespace's functions in the display functions of the classes, 

    so, the output (formated text) would look like this:

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //this is a title bar, you can set the character type in the generateTitleBar()
            Welcome to this program!        //centered text
               written by Zane              //centered text

    leftJustified            rightJustified //right justified
    
                 wrapAndCenter              //"\n" appended to the top and bottom, ie text is wrapped in "\n" and centered

    leftJustified2                          //left justified(no need to use namespace)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

*/
Last edited on
From Learn C++:

2.6 — Forward declarations and definitions - Learn C++ - https://www.learncpp.com/cpp-tutorial/forward-declarations/

Learn C++ is an online tutorial. I'd really recommend you spend some time poking around. C++ is a vast amount of info to cram into one's skull and having an alternate source won't hurt.

<stifle>*DO NOT *KVETCH* ABOUT POSSIBLE BAD UNI INSTRUCTION!*</stifle>
.find() returns type size_t which it's underlying type is different depending upon whether you're compiling as 32 bit or 64 bit. If the find doesn't succeed then the value string::npos. is returned (which is a unsigned type). You're assuming that adding 1 to this unsigned value and then casting to an int will give you -1 ?? Actually it will probably give you 0! You're then implicitly converting this int to a bool - so 0 from adding 1 becomes false and > 0 if exists becomes true. As I said, flaky.

Instead:

 
isToCenter = lineData.find("@") != std::string::npos;


and similar for the others.
@seeplus
ahh, I see, I will add that to the code instead of the int thing, Thank you for the feedback.

@Furry Guy
Thank you for the source, I will spend some time studying it.
Registered users can post here. Sign in or register to post.