Global to Local Variables?

I have a c++ project split up in two different files and headers, but I'm having a problem with one specific .cpp and .h file. In the .cpp file, there's global variables declared in it, but I have to change them to where they are global. I tried placing them inside the functions in the .cpp file it is with, but it changed the functionality of the program.

The program is supposed to sensor and show @'s over "sensitive" words and it does that just fine once these variables stay global. When I move them into the functions in the .cpp file, the program runs alright, but it doesn't censor anything and outputs an uncensored version of the message. Why is it doing that and what can I do about this to keep it's functionality without having these variables declared globally?

here's the header:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#ifndef SENSITIVEWORDS_H
#define SENSITIVEWORDS_H

#include <string>
/// HEADER FILE FOR "sensitiveWords.h"
/// To use this and it's implementation, must write #include "sensitiveWords.h" in other files.

using namespace std;

/*
 * Functions & data for maintaining and checking a list of
 * sensitive words.
 *
 */
bool isSensitive(std::string& wordFromMessage);
void addSensitiveWord (std::string& wordFromMessage);


#endif 


here's the .cpp:
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
#include "sensitiveWords.h"
#include "message.h" /// making use of the message header
file to allow the declared and implemented (message.cpp) functions to work in sensitiveWords.cpp
#include <iostream>
#include <string>
#include <fstream>
int numSensitiveWords = 0;

const int MaxSensitiveWords = 5000;
std::string sensitiveWords[MaxSensitiveWords];
/*
 * Replace all characters of a sentence containing the index pos with '@'
 * except for '/n'.
 */
 /// Implement
void censorSentenceAt (string& msg, int pos)
{
  int startcensor;
  startcensor = findSentenceStart(msg, pos);
  int stopcensor;
  stopcensor = findSentenceStop(msg, pos);

  for (int index = startcensor; index < stopcensor; ++index)
  {
    if (msg[index] != '\n')
    { msg[index] = '@'; }
  }
}

/*checks to see if a word is in the list of
*sensitive words
*/
bool isSensitive(std::string& wordFromMessage)
{
  string word = toLowerCase(wordFromMessage);
  for (int i = 0; i < numSensitiveWords; ++i)
    if (word == sensitiveWords[i])
      return true;
  return false;
}

/* */
Last edited on
Either pass the values as local arguments or create a class to encapsulate it all.

Pass as arguments
1
2
3
4
5
6
7
8
9
10
bool isSensitive(
  const std::string& wordFromMessage, 
  int numSensitiveWords, 
  std::string sensitiveWords[] )
{
  std::string word = toLowerCase(wordFromMessage);
  for (int i = 0; i < numSensitiveWords; ++i)
    if (word == sensitiveWords[i])
      return true;
  return false;

Encapsulate as class
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
struct SensitiveWordCensor
{
  const int MaxSensitiveWords = 5000;
  std::string sensitiveWords[MaxSensitiveWords];
  int numSensitiveWords;

  ...

  bool isSensitive(const std::string& wordFromMessage)
  {
    string word = toLowerCase(wordFromMessage);
    for (int i = 0; i < numSensitiveWords; ++i)
      if (word == sensitiveWords[i])
        return true;
    return false;
  }
};

Hope this helps.
@Duthomhas

I think the class one would be more convenient for me. Thank you. I do have some questions. I realized that the code I wrote down above is missing a few things. So here's the updated one

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
struct CensoringSensitive {
    const int MaxSensitiveWords = 5000;
    int numSensitiveWords;
    std::string sensitiveWords[MaxSensitiveWords];

};
bool isSensitive(std::string& wordFromMessage)
{



  string word = toLowerCase(wordFromMessage);
  for (int i = 0; i < numSensitiveWords; ++i)
    if (word == sensitiveWords[i])
      return true;
  return false;
}

/*
*adds a word to the list of sensitive words, if it is not already
*in the list of Sensitive words
*/
void addSensitiveWord (std::string& wordFromMessage)
{

  string word = toLowerCase(wordFromMessage);
  if (!isSensitive(word))
    {
      sensitiveWords[numSensitiveWords] = word;
      ++numSensitiveWords;
    }
}


so when i encapsulate in a class, does this change anything in the header file? and should it look like this:

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

struct CensoringSensitive {
    const int MaxSensitiveWords = 5000;
    int numSensitiveWords;
    std::string sensitiveWords[MaxSensitiveWords];

    ...
bool isSensitive(std::string& wordFromMessage)
{



  string word = toLowerCase(wordFromMessage);
  for (int i = 0; i < numSensitiveWords; ++i)
    if (word == sensitiveWords[i])
      return true;
  return false;
}

void addSensitiveWord (std::string& wordFromMessage)
{

  string word = toLowerCase(wordFromMessage);
  if (!isSensitive(word))
    {
      sensitiveWords[numSensitiveWords] = word;
      ++numSensitiveWords;
    }
}

};


and what are the three dots for?
Three dots are a fairly universal abbreviation for "and so on".

The header file (.hpp) should describe your class.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef TEEPER_CENSOR_HPP
#define TEEPER_CENSOR_HPP

#include <string>

struct CensoringSensitive {
    // Values used by your class
    const int MaxSensitiveWords = 5000;
    int numSensitiveWords;
    std::string sensitiveWords[MaxSensitiveWords];

    // Methods AKA "member functions"
    bool isSensitive(std::string& wordFromMessage);
    void addSensitiveWord (std::string& wordFromMessage);
};

#endif 

The .cpp file is where the methods are defined.

1
2
3
4
5
6
7
8
9
#include "censor.hpp"

#include <anything else you need that is not necessary to include in the header>

bool CensoringSensitive::isSensitive(std::string& wordFromMessage) {
    ...
}

...

:O)
@Duthomhas thank you :) I also have another .cpp file called censor.cpp and it has all of my remaining errors. It's telling me that I can't call a member function without object. What does it mean and how do I fix it?


here is my header:

1
2
3
4
5
6
7
8
9
struct Censoring{

    int numSensitiveWords;
    int MaxSensitiveWords;
    std::string sensitiveWords[];

bool isSensitive(std::string& wordFromMessage);
void addSensitiveWord (std::string& wordFromMessage);
};


here is my .cpp:


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

bool Censoring::isSensitive(std::string& wordFromMessage)
{

string word = toLowerCase(wordFromMessage);
  for (int i = 0; i < numSensitiveWords; ++i)
    if (word == sensitiveWords[i])
      return true;
  return false;
}

/*
*adds a word to the list of sensitive words, if it is not already
*in the list of Sensitive words
*/
void Censoring::addSensitiveWord(std::string& wordFromMessage)
{

  string word = toLowerCase(wordFromMessage);
  if (!isSensitive(word))
    {
      sensitiveWords[numSensitiveWords] = word;
      ++numSensitiveWords;
    }
}


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
void censorMessage (string& msg)
{


  for (int i = 0; i < msg.length(); ++i)
    {
      if (wordBeginsAt(msg, i))
	{
	  string word = extractWord(msg, i);
	  if (Censoring::isSensitive(word))
	    censorSentenceAt (msg, i);
	}
    }
}


/*
*reads sensitive words from file stream in
*/
void readSensitiveWords (istream& in)
{



  string word;
  while ((in >> word) && (word != "==="))
    Censoring::addSensitiveWord(word);
  getline (in, word);
}

/*
*reads message from file stream in
*/
string readMessage (istream& in)
{

  string msg;
  string line;
  getline (in, line);
  while (in)
    {
      msg = msg + line + "\n";
      getline (in, line);
    }
  return msg;
}

int main()
{

    /* ifstream input_text reads the 'input.txt' file which
 contains the original text file that should be censored. */
    ifstream input_text("input.txt");
    if(!input_text)
    {
        cout<<"Sorry! 'input.txt' is an invalid file."<<endl; ///Show this error
 if input.txt fails to open
    }
    /// if input_text opens fine, then do the ff:
    readSensitiveWords(input_text);
    string msg = readMessage(input_text);
    censorMessage (msg);

    /* ofstream output_text creates an output file called 
"output.txt" that writes all the changes with the censored text.
       When program is run, output.txt will display, 
with @'s necessary in the words to be censored */
    ofstream output_text;

    output_text.open("output.txt");
    output_text<<msg;
    output_text.close();

    cout << msg << flush;

    return 0;
}


I'm getting the errors in line 10 and line 27 in my censor.cpp file
You cannot use an object (variable) without an instance of it existing. Your main() should look something like:

1
2
3
4
5
6
7
8
9
10
11
int main( int argc, char** argv )
{
    CensoringSensitive censor( argv[1] ? argv[1] : "censored-words.txt" );

    std::string s;
    while (getline( std::cin, s ))
    {
        censor.censorMessage( s );
        std::cout << s << "\n";
    }
}

Your CensoringSensitive class should open and read the list of words to censor from either "censored-words.txt" or a command-line supplied filename).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
struct CensoringSenstive
{
    ...

    CensoringSensitive( const std::string& filename ):
        numSensitiveWords( 0 )
    {
        std::ifstream f( filename );
        if (!f) throw "Could not open " + filename;

        std::string word;
        while ((f >> s) && (numSensitiveWords < MaxSensitiveWords))
            sensitiveWords[ numSensitiveWords++ ] = s;
    }
};

Run the program with something like:

C:\prog\censor> dir
bad-words.txt
censor.cpp
censor.exe
input.txt

C:\prog\censor> censor bad-words.txt < input.txt > output.txt

C:\prog\censor> type output.txt
John: My old man took me *censored* fishing yesterday.
Jane: Man, you *censored* hate *censored* fishing!
John: Don't I *censored* know it!

C:\prog\censor>

Remember, a class is a type of thing, with methods that operate on data of that type. In order to use the methods, you must have a variable of that type to operate on.
Topic archived. No new replies allowed.