toupper tolower not working , help what's wrong with my code - c++

main.cpp
#include <iostream>
#include "Module2.h"
int main()
{
std::cout<<"This is a test of Module2.h"<<std::endl;
std::cout<<UCase("This is a test of UCase")<<std::endl;
std::cout<<LCase("This is a test of LCase")<<std::endl;
system("pause");
return 0;
}
Module2.h
#include <iostream>
#include "Module2.h"
int main()
{
std::cout<<"This is a test of Module2.h"<<std::endl;
std::cout<<UCase("This is a test of UCase")<<std::endl;
std::cout<<LCase("This is a test of LCase")<<std::endl;
system("pause");
return 0;
}
Module2.cpp
///////////////////////////////////////////////////
//Module : Module2.cpp
//
//Purpose : Shows the usage of modular functions
///////////////////////////////////////////////////
#include "Module2.h"
///////////////////////////////////////////////////
//UCase()
char *UCase(char *str)
{
//convert each char in the string to uppercase
//
int len = strlen(str);
for ( int i ; i < len ; i++)
{
std::cout<<"In UCase"<<std::endl;
str[i]=toupper(str[i]);
}
return str;
}
///////////////////////////////////////////////////
//LCase()
char *LCase(char *str)
{
//convert each char in the string to uppercase
//
int len = strlen(str);
for ( int i ; i < len ; i++)
{
std::cout<<"In LCase"<<std::endl;
str[i]=tolower(str[i]);
}
return str;
}
When I run it there is no warning or error .
But , it don't upper and lower the string .
I have thought my for loops are wrong , but it seems to be right .
What's wrong with my code.

The main problem is that you are trying to modify string literals such as "This is a test of UCase". This is undefined behaviour. You need to copy the literals into a char array that you can modify.
Also note that binding char* to a string literal is deprecated and forbidden, for good reason. This should have emitted a warning:
UCase("This is a test of UCase") // not good: binding char* to literal
There are other problems with your code: undefined behaviour (UB) in loops with uninitialized variables,
for ( int i ; i < len ; i++) // using uninitialized i: UB
You should also have a look at toupper and tolower documentation. They both accept int with some restrictions on their values. You have to ensure you don't pass a value that causes undefined behaviour, bearing in mind that char can be signed. See for example Do I need to cast to unsigned char before calling toupper?

Loops like this one have undefined behavior:
for ( int i ; i < len ; i++)
The reason is that you did not start i at value 0.
You have no idea what value i starts at!
It could be -10, could be 824.
If you want a value to be initialized, you have to initialize it.
I suggest:
for (int i=0; i < len; i++)

char *UCase( char *str)
{
char ch;
int i=0;
while(str[i])
{
ch=str[i];
putchar(toupper(ch));
//putchar : The value is internally converted to an unsigned char when written.
i++;
}
}
///////////////////////////////////////////////////
//LCase()
char *LCase(char *str)
{
char ch;
int i=0;
while(str[i])
{
ch=str[i];
putchar(tolower(ch));
i++;
}
}
I finally write this .
Although , I still not quite understand , but I learned
#include <ctype.h>
int tolower( int ch );
means tolower toupper can change only one character each time , so I can not
tolower ("This is a test of LCase");
code like this .

Related

How do I implement strcpy function in C++

So I have this header given to me
int mystrcpy(char *c, const char* s);
And I have to implement strcpy function myself. But when I do it and run the program, the console stops working, which I believe is a sign of memory address violation.
I tried this:
int mystrcpy(char *c, const char* s)
{
int i=0;
for(i=0;i<strlen(s);i++)
c[i]=s[i];
c[++i]=NULL;
cout<<c;
return 0;
}
Full code:
#include<iostream>
#include<cstring>
using namespace std;
class Persoana
{
char *nume;
int an;
float inaltime;
public:
int my_strcpy(char *c, const char*s);
};
int Persoana::my_strcpy(char *c, const char* s)
{
//code I need to insert
return 0;
}
int main()
{
Persoana a;
cout << endl;
cout<<a.my_strcpy("maria","george");
return 0;
}
Other posters have posted implementations of strcpy - Why you are using this in C++ code? That is an interesting question as C++ very rarely uses C style strings
The other problem is with its usage:
int main()
{
Persoana a;
cout << endl;
cout<<a.my_strcpy("maria","george");
return 0;
}
The strings "maria" and "george" are read only. Instead create an empty read/ write string as shown below that is long enough - i.e. 7 characters (do not forget the null character)
So the code should be
int main()
{
Persoana a;
char copy_of_string[7];
cout << endl;
cout<<a.my_strcpy(copy_of_string,"george");
return 0;
}
Your loop itself is OK (but inefficient, since you call strlen() on every iteration). The real problem is when you go to insert the null terminator at the end of the copied string. You are incrementing i again before inserting the terminator. DON'T do that. i is already at the correct index after the loop ends, so just use it as-is:
int mystrcpy(char *c, const char* s);
{
int i, len = strlen(s);
for(i = 0; i < len; ++i)
c[i] = s[i];
c[i] = '\0'; // <-- NO ++ HERE!
cout << c;
return 0;
}
That being said, the simplest way to implement strcpy without using i at all is as follows:
int mystrcpy(char *c, const char* s)
{
char *p = c;
while (*p++ = *s++);
cout << c;
return 0;
}
If you remove the cout then it becomes simpler:
int mystrcpy(char *c, const char* s)
{
while (*c++ = *s++);
return 0;
}
No matter what, make sure that when you call mystrcpy(), c is pointing to a char[] buffer that is allocated to at least strlen(s)+1 chars in size, otherwise the code will have undefined behavior.
The for loop
for(i=0; i < strlen(s); i++)
aborts when i < strlen(s) becomes false, which is the case when i is equal to strlen(s). So that will be the value of i when the loop ends.
C strings are NULL-terminated as you know, so you need strlen(s) + 1 bytes reserved for c. Since you increment i again before writing the '\0' character, you're using strlen(s) + 2 bytes starting at c.
If c is exactly the size that's needed (strlen(s) + 1), that may lead to an access violation, since you're writing past the end of the allocated memory.
So instead of
c[++i]=NULL;
write
c[i]='\0';
Hope this makes sense!

C++ Combining two zero terminated strings?

So I am doing a question where I have to join two zero terminated strings, the first contains a word, and the second is empty and twice the size of the original array. I was able to get this working using the following code
#include <stdio.h>
#include <iostream>
using namespace std;
int main()
{
char str1[] = "test";
char str2[(sizeof(str1)-1)*2];
char *p;
int count = 0;
for(p = str1; *p != 0; p++) {
str2[count] = *p;
count++;
}
cout << str2;
}
However I have to use a function with the following prototype
char *combine(char *a);
So I tried this
#include <stdio.h>
#include <iostream>
using namespace std;
char *copy_and_reverse(char *a) {
char str2[8];
int count = 0;
char* b = str2;
for(a; *a != 0; a++) {
str2[count] = *a;
count++;
}
return b;
}
int main()
{
char str1[] = "test";
char *a;
a = str1;
char* b = copy_and_reverse(a);
for(b; *b != 0; b++) {
cout << *b;
}
}
But it does not work (it is printing the string but it's printing a few random characters after it), I'm getting so confused with the pointers, can anyone help me out with this?
Edit: here is the question I am trying to answer
Write a function in C++ that takes as a char * style zero terminated string and returns a char* string twice the length of the input. The first half of the returned string should contain a copy of the contents of the original array. The second half of the string should contain the contents of the original string in reverse order.
The function should have the following prototype:
char *copy_and_reverse(char* a);
Note: you should not use any library functions (e.g from string.h).
There are two big problems in your copy_and_reverse code.
After copying the input string, you are not terminating the result. This means str2 is not a valid string. Fix:
str2[count] = '\0'; // after the loop
copy_and_reverse returns a pointer to a local variable (str2). After the function returns, all its local variables are gone, and main is dealing with an invalid pointer. To fix this, either use static memory (e.g. by declaring str2 as static or making it a global variable) or dynamic memory (allocate storage with new[] (or malloc())). Both approaches have their disadvantages.
Minor stuff:
variable; does nothing (see for (a; ...), for (b; ...)).
str2 isn't big enough for the final result. str1 is 5 bytes long ('t', 'e', 's', 't', '\0'), so char str2[8] is sufficient for now, but in the end you want to allocate length * 2 + 1 bytes for your result.
I believe that this will suit your needs:
#include <stdio.h>
#include <stdlib.h>
static char* copy_and_reverse(char* a);
static int strlen(char *c); // self-implemented
int main(void) {
char *a = "some string";
char *b = copy_and_reverse(a);
printf("%s", b);
free(b);
return 0;
}
static char* copy_and_reverse(char* a) {
int n = strlen(a);
char *b = new char[n * 2 + 1]; // get twice the length of a and one more for \0
for (int i = 0; i < n; ++i) { // does copying and reversing
b[i] = a[i];
b[i+n] = a[n-i-1];
}
b[2 * n] = '\0'; // null out last one
return b;
}
static int strlen(char *c) {
char *s = c;
while( *s++ );
return s-c-1;
}

Reverse String C++ using char array

I wrote a simple C++ program to reverse a string. I store a string in character array. To reverse a string I am using same character array and temp variable to swap the characters of an array.
#include<iostream>
#include<string>
using namespace std;
void reverseChar(char* str);
char str[50],rstr[50];
int i,n;
int main()
{
cout<<"Please Enter the String: ";
cin.getline(str,50);
reverseChar(str);
cout<<str;
return 0;
}
void reverseChar(char* str)
{
for(i=0;i<sizeof(str)/2;i++)
{
char temp=str[i];
str[i]=str[sizeof(str)-i-1];
str[sizeof(str)-i-1]=temp;
}
}
Now this method is not working and, I am getting the NULL String as result after the program execution.
So I want to know why I can't equate character array, why wouldn't this program work. And what is the solution or trick that I can use to make the same program work?
sizeof(str) does not do what you expect.
Given a char *str, sizeof(str) will not give you the length of that string. Instead, it will give you the number of bytes that a pointer occupies. You are probably looking for strlen() instead.
If we fixed that, we would have:
for(i=0;i<strlen(str)/2;i++)
{
char temp=str[i];
str[i]=str[strlen(str)-i-1];
str[strlen(str)-i-1]=temp;
}
This is C++, use std::swap()
In C++, if you want to swap the contents of two variables, use std::swap instead of the temporary variable.
So instead of:
char temp=str[i];
str[i]=str[strlen(str)-i-1];
str[strlen(str)-i-1]=temp;
You would just write:
swap(str[i], str[sizeof(str) - i - 1]);
Note how much clearer that is.
You're using C++, just use std::reverse()
std::reverse(str, str + strlen(str));
Global variables
It's extremely poor practice to make variables global if they don't need to be. In particular, I'm referring to i about this.
Executive Summary
If I was to write this function, it would look like one of the two following implementations:
void reverseChar(char* str) {
const size_t len = strlen(str);
for(size_t i=0; i<len/2; i++)
swap(str[i], str[len-i-1]);
}
void reverseChar(char* str) {
std::reverse(str, str + strlen(str));
}
When tested, both of these produce dlrow olleh on an input of hello world.
The problem is that within your function, str is not an array but a pointer. So sizeof will get you the size of the pointer, not the length of the array it points to. Also, even if it gave you the size of the array, that is not the length of the string. For this, better use strlen.
To avoid multiple calls to strlen, give the function another parameter, which tells the length:
void reverseChar(char* str, int len)
{
for(i=0; i<len/2; i++)
{
char temp=str[i];
str[i]=str[len-i-1];
str[len-i-1]=temp;
}
}
and call it with
reverseChar(str, strlen(str))
Another improvement, as mentioned in the comments, is to use std::swap in the loop body:
void reverseChar(char* str, int len)
{
for(i=0; i<len/2; i++)
{
std::swap(str[i], str[len-i-1]);
}
}
Also, there is std::reverse which does almost exactly that.
//reverse a string
#include<iostream>
using namespace std;
int strlen(char * str) {
int len = 0;
while (*str != '\0') {
len++;
str++;
}
return len;
}
void reverse(char* str, int len) {
for(int i=0; i<len/2; i++) {
char temp=str[i];
str[i]=str[len-i-1];
str[len-i-1]=temp;
}
}
int main() {
char str[100];
cin.getline(str,100);
reverse(str, strlen(str));
cout<<str<<endl;
getchar();
return 0;
}
If I were you, I would just write it like so:
int main()
{
string str;
cout << "Enter a string: " << endl;
getline(cin, str);
for (int x = str.length() - 1; x > -1; x--)
{
cout << str[x];
}
return 0;
}
This is a very simple way to do it and works great.
#include <iostream>
#include <cstdio>
using namespace std;
int main()
{
char str[80];
cout << "Enter a string bro: \n";
gets_s(str);
for (int i = strlen(str) - 1; i > -1; i--)
{
cout << str[i];
}
}

C++ basic syntax errors

I am getting errors with the following code and don't know where I am going wrong.
#include <iostream>
#include <fstream>
#include <cstring>
#include "Translator.h"
using namespace std;
int main (void)
{
char Dictionary::translate (char out_s[], const char s[])
{
int i;
for (i=0;i < numEntries; i++)
{
if (strcmp(englishWord[i], s)==0)
break;
}
if (i<numEntries)
strcpy(out_s,elvishWord[i]);
}
char Translator::toElvish(char elvish_line[],const char english_line[])
{
int j=0;
char temp_eng_words[2000][50];
//char temp_elv_words[2000][50]; NOT SURE IF I NEED THIS
std::string str = english_line;
std::istringstream stm(str);
string word;
while( stm >> word) // read white-space delimited tokens one by one
{
int k=0;
strcpy (temp_eng_words[k],word.c_str());
k++;
}
for (int i=0; i<2000;i++) // ERROR: out_s was not declared in this scope
{
Dictionary::translate (out_s,temp_eng_words[i]); // ERROR RELATES TO THIS LINE
}
}
Translator::Translator(const char dictFileName[]) : dict(dictFileName)
{
char englishWord[2000][50];
char temp_eng_word[50];
char temp_elv_word[50];
char elvishWord[2000][50];
int num_entries;
fstream str;
str.open(dictFileName, ios::in);
int i;
while (!str.fail())
{
for (i=0; i< 2000; i++)
{
str>> temp_eng_word;
str>> temp_elv_word;
strcpy(englishWord[i],temp_eng_word);
strcpy(elvishWord[i],temp_elv_word);
}
num_entries = i;
}
str.close();
}
}}
The first error I get is around
char Dictionary::translate (char out_s[], const char s[])
{
int i;
where it says "A function definition is not allowed before a '{' token. The second error I get is at the that there is an expected '}' at the end of input, but no matter how many i put in or leave out it still gives the same error message.
And ideas??
You're defining all the functions inside main(). Move them all before main().
You shouldn't define a function right within another function.
Function definitions come after each other.
It's not allowed to declare inner functions in C++.
Move your functions to a distinct scope, without nesting into main.

passing vector<char> to a pointer char*

how do I pass a char vector to a char*? I know this problem could easily be solved with a predefined char[] array with a SIZE const, but I want the flexibility of a vector because there will be no predefined size.
using namespace std;
//prototype
void getnumberofwords(char*);
int main() {
//declare the input vector
vector<char> input;
/*here I collect the input from user into the vector, but I am omitting the code here for sake of brevity...*/
getnumberofwords(input);
//here is where an ERROR shows up: there is no suitable conversion from std::vector to char*
return 0;
}
void getnumberofwords(char *str){
int numwords=0;
int lengthofstring = (int)str.size();
//this ERROR says the expression must have a case
//step through characters until null
for (int index=0; index < lengthofstring; index++){
if ( *(str+index) == '\0') {
numwords++;
}
}
}
You can use data() member to get the pointer to the underlying array:
getnumberofwords(input.data());
The most obvious is to pass &your_vector[0]. Be sure to add a NUL to the end of your vector first though.
Alternatively, use std::string instead of std::vector<char>, in which case you can get a NUL-terminated string with the c_str member function.
Edit: I have to wonder, however, why getnmberofwords would be written to accept a char * unless it's some old C code that you just can't get away from using.
Given a typical definition of "word" counting some words that start out in a string can be done something like this:
std::istringstream buffer(your_string);
size_t num_words = std::distance(std::istream_iterator<std::string>(buffer),
std::istream_iterator<std::string>());
You should pass the reference of the vector to the function getnumberofwords.
void getnumberofwords(vector<char>& str){
int numwords=0;
int lengthofstring = str.size();
for (int index=0; index < lengthofstring; index++){
if ( str[index] == '\0') {
numwords++;
}
}
}
There is no method for converting the type from vector to pointer.
here's what I ended up doing which worked:
#include <iostream>
#include <cstring>
#include <string>
#include <iomanip>
using namespace std;
//prototype
void getnumberofwords(char*);
void getavgnumofletters(char*, int);
int main() {
const int SIZE=50;
char str[SIZE];
cout<<"Enter a string:";
cin.getline(str, SIZE);
getnumberofwords(str);
return 0;
}
void getnumberofwords(char *str){
int numwords=0;
int lengthstring=strlen(str);
//step through characters until null
for (int index=0; index < lengthstring; index++){
if (str[index] ==' ') {
numwords++;
}else{
continue;
}
}
numwords+=1;
cout<<"There are "<<numwords<<" in that sentence "<<endl;
getavgnumofletters(str, numwords);
}
void getavgnumofletters(char *str, int numwords) {
int numofletters=0;
double avgnumofletters;
int lengthstring=strlen(str);
//step through characters until null
for (int index=0; index < lengthstring; index++){
if (str[index] != ' ') {
numofletters++;
}else{
continue;
}
}
avgnumofletters = (double)numofletters/numwords;
cout<<"The average number of letters per word is "<<setprecision(1)<<fixed<<avgnumofletters<<endl;
}
/*