Reversing a String : Garbage Values - c++

I have written a code to reverse a string
#include < iostream >
#include < cstring >
using namespace std;
string Reversal(char * s);
int main()
{
char str[25];
cout << "Enter a Name :";
cin.get(str, 25);
cout << "You have entered: " << str;
cout << "\nReversed : " << Reversal(str);
return 0;
}
string Reversal(char * s)
{
int count = strlen(s);
char temp[count];
for (int i = 0; i < count; i++)
{
temp[i] = * (s + (count - 1) - i);
}
return temp;
}
Have referred below link to make cin take whitespaces as input:
How to cin Space in c++?
But the output is showing a few junk characters ? Any suggestion why so?

When you implicitly construct a std::string from temp, the latter is expected to be NUL-terminated, which it isn't.
Change
return temp;
to
return std::string(temp, count);
This uses a different constructor, one that takes an explicit character count and doesn't expect temp to be NUL-terminated.

The last character in the temp array should be null-terminated. Make it 1 longer than the size of your input string. Make the last character the null character ('\0').
string Reversal(char *s)
{
int count=strlen(s);
char temp[count+1]; //make your array 1 more than the length of the input string
for (int i=0;i<count;i++)
{
temp[i]= *(s+(count-1)-i);
}
temp[count] = '\0'; //null-terminate your array so that the program knows when your string ends
return temp;
}
The null character specifies the end of the string. Usually it is a byte with all 0 bits. If you don't specify this as the last character of your temp array, the program will not know when is the end of your array of characters. It will keep including every character until it finds a '\0'.

Related

Why is c++ treating the space bar as null ('\0')?

my professor asked us to determine the number of vowels in userString without a call to the library.
I am using '\0' in a for loop to figure out when will the string the user input will come to an end because I don't know the exact size they are going to input for the string. I am a beginner programmer so please don't give me complcated answer! thanks.
I have for(int i = 0; userString[i] != '\0'; i++)
but the program is treating the space bar as a null character too so
I get a problem in the output,
if I have a space in the commend line is treats it as a null and terminates the proram
loop at the pictue of the 2 different outputs for refrence.
As you can see in output 1
When i have "MianJalal" I get 9 in the terminal but for
output 2 When I have "Mian Jalal" (with a space), it treats the space as null and gives me 4, I am aware that '\0' is space in the special chartacer in c++ but it's also null, how can I tell the program i mean null not space?
this is my code,
#include <iostream>
using namespace std;
int main()
{
int numOfVowels = 0;
int length = 0;
char userString[50]; // The string the user will input
cout << "Enter a sentence to find out how many vowels are in the sentence" << endl;
cin >> userString;
for(int i = 0; userString[i] != '\0'; i++) // '\0' means null in a string in c++; if a user doesn't use a index in a char string
{ // the program will know it's a null in syntax '\0'
if(userString[i] == 'A' or userString [i] == 'a' or userString[i] == 'i')
{
numOfVowels++;
}
length++;
}
cout << length << endl;
return 0;
}
The problem is that the operator >> uses the space as a delimiter. So when reading userString it stops at the first space. To avoid this a method could be to use istream::getline (char* s, streamsize n ) function, that reads the entire line up to the '\n' character, or the supplied size limit.
#include <iostream>
using namespace std;
int main()
{
int numOfVowels = 0;
int length = 0;
char userString[50]; // The string the user will input
cout << "Enter a sentence to find out how many vowels are in the sentence" << endl;
cin.getline(userString, sizeof(userString));
for(int i = 0; userString[i] != '\0'; i++) // '\0' means null in a string in c++; if a user doesn't use a index in a char string
{ // the program will know it's a null in syntax '\0'
if(userString[i] == 'A' or userString [i] == 'a' or userString[i] == 'i')
{
numOfVowels++;
}
length++;
}
cout << length << endl;
return 0;
}

Extra character being added to string

Why is there an extra character at the end of my string?
#include <iostream>
using namespace std;
int main() {
int num;
cin >> num; // Reading input from STDIN
cout << "Input number is " << num << endl; // Writing output to STDOUT
char c1, s2[10];
for (int i=0; i<num; i++)
{
cin >> c1;
if(c1==0){
break;
}
s2[i] = c1;
}
cout <<"output= "<< s2;
}
output example
4
Input number is 4
a l e x
output= alex#
Why is the "#" being added to the end of the string? At first i thought it was a random garbage value but every time I run the program its always the same symbol
cout, when printing a c-string, expects it to zero terminated. Whereas you haven't done so for the array s2.
You can zero initialize the entire array:
char s2[10] = {};
Or just zero terminate the last byte:
int i = 0;
for (i=0; i<num; i++)
{
cin >> c1;
if(c1==0) {
break;
}
s2[i] = c1;
}
s2[i] = '\0';
In any case, you need to be wary of potential buffer overflow (e.g. if num is too large).
Alternatively, you can consider using std::string instead of a fixed length array.
You're reading from a memory location that hasn't been initialized. By using an array of ten characters and only initializing the first four (or whatever else the number is), all other characters stay uninitalized. What data is actually read from an uninitialized location is undefined, meaning it's pretty much up to your compiler that chooses to read the equivalent value of "#" from that location. You can fix that issue by using a memory bit of the appropriate size. For this, you just replace the line
char c1, s2[10];
with
char c1;
char* c2 = new char[num + 1] //num + 1 is necessary to contain a string terminator, see the other answers
this way, you dynamically allocate exactly the size you need.
Don't forget to delete[] c2; afterwards.
You are using a Character sequence well explained here.
By convention, the end of strings represented in character sequences
is signaled by a special character: the null character, whose literal
value can be written as '\0' (backslash, zero).
In this case, the array of 20 elements of type char called foo can be
represented storing the character sequences "Hello" and "Merry Christmas" as:
Notice how after the content of the string itself, a null character
('\0') has been added in order to indicate the end of the sequence.
The panels in gray color represent char elements with undetermined
values.
I offer a c++17 solution with the constructor initialization although I may prefer either a dynamic array or std::string instead of a char.
I also added a simple integer check that always should be used.
Also a few versions of avoiding the use of the whole namespace std for various reasons, mostly to avoid unnecessary errors.
#include <iostream>
#include <limits> //numeric_limits
using std::cout, std::endl, std::cin; //<- explicit declared
int main() {
int num;
while(!(cin >> num)){ //check the Input format for integer the right way
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
cout << "Invalid input. Try again: ";
};
cout << "Input number is " << num << endl;
char c1, s2[num+1]{}; // Initialize with an empty string
for (int i = 0; i < num; i++)
{
cin >> c1;
if (c1 == 0) {
break;
}
s2[i] = c1;
}
cout << "output= " << s2 << endl;
return 0;
}
This happens because s2 is actually not a string and does not have the \0 character, which would mean the end of the string. Therefore, cout prints your string and will continue to move further in memory, byte by byte, interpreting each of them as a character to be output until it encounters the \0 character. In order to fix this, you can initialize s2 with an empty string, so the array will initially be completely filled \0.
#include <iostream>
using namespace std;
int main() {
int num;
cin >> num;
cout << "Input number is " << num << endl;
char c1, s2[10] = ""; // Initialize with an empty string
for (int i = 0; i < num; i++)
{
cin >> c1;
if (c1 == 0) {
break;
}
s2[i] = c1;
}
cout << "output= " << s2;
}

I need to return number of words in c sting after taking user input

I need to make a program that takes input from the user and then return the number of words entered to the string. I store user input in array char words[256]; I have a function called countWords. It loops though the array and if it encounters a space he counter is increased. if(words[i] == '\0') if the null character is reached the counter is stopped. It then return nSpaces + 1 to account for the first word.
But my output seems to produce the number of characters in the string instead. How can this be fixed.
#include <iostream>
#include <cstdlib>
using namespace std;
//Function Prototype
int countWords(char words[]);
int main(){
char words[256];
cout << "Enter a sentence: ";
cin.getline(words, 256);
int word_num = countWords(words);
cout << "The number of words in a string is: " << word_num << endl;
system("PAUSE");
return 0;
}
int countWords(char words[]){
int nSpaces = 0;
//unsigned int i = 0;
/*while(isspace(words[i])){
i++;
}*/
for (int i=0; i<256; i++){
if(isspace(words[i])){
nSpaces++;
// Skip over duplicate spaces & if a NULL character is found, we're at the end of the string
//while(isspace(words[i++]))
if(words[i] == '\0')
nSpaces--;
}
}
// The number of words = the number of spaces + 1
return nSpaces + 1;
}
The Output is:
Enter a sentence: Yury Stanev
The number of words in a string is: 7
You're not stopping the loop when you get to the null character. You're only testing for the null character inside the if(isspace(words[i])) block, but if the character is a space then it can't also be the null terminator. As a result, you're reading past the end of the input, and counting the spaces in the uninitialized part of the string.
int countWords(char words[]){
int nSpaces = 0;
for (int i=0; i<256 && words[i] != '\0'; i++){
if(isspace(words[i])){
nSpaces++;
}
}
// The number of words = the number of spaces + 1
return nSpaces + 1;
}
isspace counts new lines (\n), tabs (\t), \v, \f and \r.
Probably you want only white-spaces? Check for " " and "\t" only.

Store a word into a dynamically created array when first encountered

Here is the assignment:
Write a program that reads in a text file one word at a time. Store a word into a dynamically created array when it is first encountered. Create a paralle integer array to hold a count of the number of times that each particular word appears in the text file. If the word appears in the text file multiple times, do not add it into your dynamic array, but make sure to increment the corresponding word frequency counter in the parallel integer array. Remove any trailing punctuation from all words before doing any comparisons.
Create and use the following text file containing a quote from Bill Cosby to test your program.
I don't know the key to success, but the key to failure is trying to please everybody.
At the end of your program, generate a report that prints the contents of your two arrays in a format similar to the following:
Word Frequency Analysis
I 1
don't 1
know 1
the 2
key 2
...
Here is my code:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int readInFile (string tempArray [], string file, int arraySize);
int main()
{
ifstream inputFile;
string *readInArray = 0,
*compareArray = 0,
filename,
word;
int wordCount = 0;
int encountered = 0;
int j = 0,
*wordFrequency = 0;
cout << "Enter the filename you wish to read in: ";
getline(cin, filename);
inputFile.open(filename.c_str());
if (inputFile)
{
while (inputFile >> word)
{
wordCount++;
}
inputFile.close();
readInArray = new string[wordCount];
readInFile(readInArray, filename, wordCount);
}
else
{
cout << "Could not open file, ending program";
return 0;
}
compareArray = new string[wordCount];
wordFrequency = new int[wordCount];
for (int count = 0; count < wordCount; count++)
wordFrequency[count] = 0;
for(int i = 0; i < wordCount; ++i)
{
j = 0;
encountered = 0;
do
{
if (readInArray[i] == compareArray[j])
encountered = 1;
++j;
} while (j < wordCount);
if (encountered == 0)
{
compareArray[i]=readInArray[i];
wordFrequency[i] += 1;
}
}
for(int k=0; k < wordCount; ++k)
{
cout << "\n" << compareArray[k] << " ";
}
for(int l=0; l < wordCount; ++l)
{
cout << "\n" << wordFrequency[l] << " ";
}
return 0;
}
int readInFile (string tempArray [], string file, int arraySize)
{
ifstream inputFile;
inputFile.open(file.c_str());
if (inputFile)
{
cout << "\nHere is the text file:\n\n";
for(int i=0; i < arraySize; ++i)
{
inputFile >> tempArray[i];
cout << tempArray[i] << " ";
}
inputFile.close();
}
}
Here is my question:
How do you store a word into a dynamically created array when it is first encountered? As you can see from my code made a string array with some of the elements empty. I believe it is suppose to be done using pointers.
Also how do I get rid of the punctuation in the string array? Should it be converted to a c-string first? But then how would I compare the words without converting back to a string array?
Here is a link to a java program that does something similar:
http://math.hws.edu/eck/cs124/javanotes3/c10/ex-10-1-answer.html
Thank you for any help you can offer!!
As to the first part of your question, you are not using a dynamically created array. You are using a regular array. C++ provides implementations of dymnamic arrays, like the vector class http://www.cplusplus.com/reference/vector/vector/
As to the second part of your question, I see no reason to convert it to a c string. The string class in c++ provides functionality for removing and searching for characters. http://www.cplusplus.com/reference/string/string/
The string::erase function can be used to erase punctuation characters found with string::find.
Note: There are other ways of doing this assignment that may be easier (like having an array of structs containing a string and an int, or using a map) but that may defeat the purpose of the assignment.

Counting individual word lengths in a string

#include <iostream>
#include <string>
#include <cctype>
size_t countwords(const char *);
using namespace std;
int main()
{
char a[] = "Four score and seven years ago";
float sum = 0.0;
char j[10];
string s;
int size = sizeof(a)/sizeof(char);
for(int i = 0; i < size; i++){
if(!isspace(a[i])){
s += a[i];
}
if(isspace(a[i]) and !isspace(a[i + 1])){
cout << s << " " << s.length() << endl;
sum += s.length();
s = "";
}
}
cout << countwords(a);
return 0;
}
size_t countwords( const char *s )
{
size_t count = 0;
while ( *s )
{
while ( isspace( *s )) ++s;
if ( *s ) ++count;
while ( isalnum( *s )) ++s;
}
return ( count );
}
In the main function, I am able to print each word and it's word length. such as four 4, score 5 etc. I am having trouble handling the last word "ago." I don't know how to account for that. Any help would be appreciated.
Output:
Four 4
score 5
and 3
seven 5
years 5
▼ 2
6
and yeah, don't know why that black triangle is in the output but this is the exact output.
The terminating NULL character is not considered whitespace, so your second if condition returns false when it encounters the end of the string.
Seems to me the statements within the for statement can be simplified to
if(!isspace(a[i]) && a[i]){
s += a[i];
} else {
cout << s << " " << s.length() << endl;
sum += s.length();
s = "";
}
Also, breaking the string apart at whitespace can be done easily using an istringstream
char a[] = "Four score and seven years ago";
std::istringstream ss(a);
std::string s;
while(ss >> s) {
std::cout << s << ' ' << s.length() << '\n';
}
The string you try to inspect is one character longer than you expect:
int size = sizeof(a)/sizeof(char);
This size includes the terminating null character. If I were to deal with the assignment I would either operator on char const* and use the C convention of checking against a terminating null character or I would convert the array into a std::string and deal with iterator and check against the end iterator. I also think that the logic you have to check against the end of a word assumes that words are separated by exactly one space.
Your countwords() function seems to deal with the C convention. Your main() function should check against a[i] being null before using !isspace(static_cast<unsigned char>(a[0])): the countwords() works because isspace(0) and isalnum(0) are false. However, just because 0 isn't a space it means it is part of a word. You should also consider the terminating null character a word separator, i.e., the condition to report the length of a word should be
if(!a[i] || isspace(static_cast<unsigned char>(a[i])))
std::string word;
std::istringstream str(a);
while (str >> word) {
sum += str.length();
std::cout << word << ' ' << word.length << '\n';
}