I have a function that at the moment doesn't do anything because the char array I send as parameter has no value. I can write out the data before the function and get the expected output but if I write out in the function nothing come out even if It's the first thing I do.
I first write out the string and then convert it to a char array. I have also tried with just a normal string as parameter with the same result.
std::cout << block;
block = this->removeNullCharacters(block.c_str());
Output of the first cout is : "0/"
The output of the function below is nothing. Nothing at all is shown up in the console.
std::string FileSystem::removeNullCharacters(const char * input){
std::string out = "";
for(int i = 0; i < 512; ++i){
std::cout << i << ": " << input[i];
/*if(input[i] == '\0'){
return out;
}
else{
out += input[i];
}*/
}
return out;
}
Not clear at all what you try to achieve or, in other words, you question is not complete.
input is a pointer to char and points to the first element of an array of chars of size 512.
out is an empty string and returned at the end of the function.
block is schizophren, a pointer to char and a std::string at the same time i guess. You need to fix this one really.
Try this. I think you want to pass a pointer to a sequence of chars to the function and concatenate each char to the string until the end of the sequence (which is terminated by \0). Forget about the size completely and simply use the null termination as a loop condition.
std::string FileSystem::removeNullCharacters(const char * input){
std::string out = "";
for(int i = 0; input[i] != '\0'; ++i){
std::cout << i << ": " << input[i];
out += input[i];
}
return out;
}
But you gotta make sure you pass in an array of chars or a valid pointer to char (which is the beginning of a sequence of chars and the last element is \0).
Related
I'm trying to invert the case of some strings, and I did it, but I have some extra characters in my return, is it a memory problem? Or because of the length?
char* invertirCase(char* str){
int size = 0;
char* iterator = str;
while (*iterator != '\0') {
size++;
iterator++;
}
char* retorno = new char[size];
for (int i = 0; i < size; i++) {
//if capital letter:
if (str[i] < 96 && str[i] > 64) {
retorno[i] = str[i] + 32;
}
// if lower case:
else if (str[i] > 96 && str[i] < 123) {
retorno[i] = str[i] - 32;
}
//if its not a letter
else {
retorno[i] = str[i];
}
}
return retorno;
}
For example, if I try to use this function with the value "Write in C" it should return "wRITE IN c", but instead it returns "wRITE IN cýýýýÝݱ7ŽÓÝ" and I don't understand where those extra characters are coming from.
PS: I know I could use a length function, but this is from school, so I can't do that in this case.
add +1 to the size of the char array.
char* retorno = new char[size+1];
add a null-terminated string before returning retorno.
retorno[size] = '\0';
Your output string is not null-terminated
When you iterate through the input string, you increment size until you reach null. That means the null is not copied to the output string. After you exit the loop, you should increment size once more to capture the end.
As an aside, it's probably a good idea to constrain size to some maximum (while(*iterator != '\0' && size < MAXSIZE)) in case someone passes a non-terminated string into your function. If you hit the max size condition, you'd need to explicitly add the null at the end of your output.
Your string should be null terminated; which is what you are looking for when you get the initial size of the string. When you create the new string, you should allocated size+1 chars of space, then retorno[size] should be set to a null terminating character (i.e. '\0'). When you attempt to print a char* using printf or cout (or similar mechanisms), it will keep printing characters until it find the null terminating character, which is why you are getting the garbage values after your expected output.
On another note, c++ has helpful functions like std::islower / std::isupper and std::tolower / std::toupper
From what I can tell, there could be 2 things going on here:
Like everyone here mentioned, the absence of a null terminating character ('\0') at the end of your char array could be causing this.
It could be the way you are printing results of your retorno character string outside of your invertirCase() function.
I tested out your function in C++14, C++17 and C++20 and it returned the correct result each time, both with the null terminating character at the end of the retorno char array and without it.
Try printing your result inside of your function before returning it, to identify if this is being caused inside of your function or outside of it. Like so:
char* invertirCase(char* str){
// [... truncated code here]
for (int i = 0; i < size; i++) {
// [... truncated code here]
}
cout << " **** TESTING INSIDE FUNCTION ****" << endl;
cout << "-- Testing index iteration" << endl;
for (int i = 0; i < size; i++) {
cout << retorno[i];
}
cout << endl;
cout << "-- Testing iterator iteration" << endl;
for (char* iterator = retorno; *iterator != '\0'; iterator++) {
cout << *iterator;
}
cout << endl;
cout << "-- Testing advanced for loop" << endl;
for (char character : retorno) {
cout << character;
}
cout << " **** END TESTING ****" << endl;
cout << endl;
return retorno;
}
This way you could possibly identify both if the problem occurs inside of your function or if the problem is occurring because of the way you may be printing your result as well.
I need some kind of error handler if I enter a string larger than the set size.
cout << "Enter long of the string" << endl;
cin >> N;
char* st = new char[N];
char* st1 = new char[N];
for (int i = 0; i < N; ++i) {
*(st1 + i) = ' ';
}
cout << "Enter string in the end put 0,without whitespace in the end." << endl;
cin.getline(st, N, '0');
First some comments.
Do not use C-Style arrays in C++ (like char data[N])
Always use std::string for strings
Never use char arrays for strings
Never ever use raw pointers for owned memory in C++
Neally never use new in C++
Avoid using pointer arithmetic with raw pointers pointing to owned memory
So, you should rethink your design. Start doing it correctly in the first place.
To answer you concrete question: If you read the documentation of the getline, then you can see that
count-1 characters have been extracted (in which case setstate(failbit) is executed).
So, the failbit will be set. You can check this with
if (std::cin.rdstate() == std::ios_base::failbit)
But as you can also read in the documentation
Extracts characters from stream until end of line or the specified delimiter delim.
So, it will not work, as you expect, It will try to read until 0 has been read. I think it will not work for you.
You also need to delete the newed memory. Otherwise, you are creating a memory hole. Look at you example again and try it:
#include <iostream>
int main() {
size_t N;
std::cout << "Enter maximum length of the string\n";
std::cin >> N;
char* st = new char[N];
char* st1 = new char[N];
for (size_t i = 0U; i < N; ++i) {
*(st1 + i) = ' ';
}
std::cout << "Enter string in the end put 0, without whitespace in the end.\n";
std::cin.getline(st, N, '0');
if (std::cin.rdstate() == std::ios_base::failbit) {
std::cin.clear();
std::cout << "\nError: Wrong string entered\n\n";
}
delete[] st;
delete[] st1;
return 0;
}
Solution for all your problems: Use std::string and std::getline
No matter what value I set for the size of my array, the function I wrote returns a value some degree larger.
I've tried, while(*str++) and removing the str++ from inside the while loop, instead of what is there now.
I am using Visual Studio 2019.
int strlen(char* str)
{
int i = 0;
while (*str != '\0')
{
i++;
str++;
}
return i;
}
int main()
{
char line[1];
char* v = line;
char* s = new char[1];
cout << "for s " << strlen(s) << endl;
cout << "for v " << strlen(v) << endl;
}
You are neglecting to null-terminate your strings. Your function is iterating past the end of the array and causing Undefined Behavior. Some string-manipulation functions will put the null at the end, but if you want your string to have a terminal null, you must put it there yourself.
char line[2];
char* v = line;
line[0]='x';
line[1]= '\0';
The contents of your arrays are undefined. You are not filling any of the arrays with any characters, let alone with any null terminators. It is undefined behavior to call strlen() on a character array that is not properly null terminated.
I am passing a string to my function, and the function is supposed to use that string to put individual chars in a stack. Then the stack is supposed to spit it back out (Since it's a stack it should be reversed). For example if my string is hello, it should print "olleh". But instead I'm getting ooooo. I think it has something to do with the fact that I'm setting ch equal to a different character every time but I'm not sure how to input those character in a different way.
void Stack::function2reverse(string myString) {
int countItIt = 0;
int sizeOfString = myString.size();
char Ch ;
for (int i= 0; i< sizeOfString; x++)
{
Ch = myString[x];
stack.push(Ch);
countIt ++;
}
while (countIt != 0)
{
cout << Ch;
stack.pop();
countIt --;
}
}
cout << Ch; - you print the same character every time (the last one entered, so 'o').
Instead, print the top character in the stack: std::cout << stack.top().
std::stack keeps track of its own size, so you don't need to worry about that either. Then you can replace your print loop with:
while (!stack.empty()) {
std::cout << stack.top();
stack.pop();
}
And of course, the Standard Library provides a std::reverse function anyway, so if this was not just an exercise in learning about std::stack, you could use that (and I can think of several other things to do as well, depending on exactly what you are trying to achieve):
std::string s = "hello";
std::reverse(std::begin(s), std::end(s));
// s now contains "olleh"
You may also want to read up on why using namespace std; is a bad practice.
I'm rusty on using classes and am brushing up on using them. I've encountered a problem where I'm attempting to use a simple program to retrieve data from a file that holds a simple number ("1234" in this case).
#include <iostream>
#include <fstream>
class hold
{
public:
void enter();
hold();
private:
char x[50];
};
hold::hold()
{
x[50] = NULL;
}
void hold::enter()
{
std::ifstream inFile;
inFile.open("num.txt");
int pos = 0;
while(inFile.good())
{
inFile >> x[pos];
pos++;
}
std::cout << "strlen(x) = " << strlen(x) << std::endl;
for(int i = 0; i < strlen(x); i++)
{
std::cout << x[i] << " ";
}
std::cout << std::endl;
}
int main()
{
hold h;
h.enter();
system("pause");
return 0;
}
The output is:
strlen(x) = 50;
1 2 3 4 (following a bunch of signs I do not know how to print).
It's been almost a year since I've consistently practiced classes and I don't recall having used a character array in a class. Can anyone tell me where I'm messing up with this file not terminating after "4"? I've tried using if statements to break the while loop if "x[pos] == '\0', but it didn't work either.
You did not terminate your string and you have undefined behaviour because strlen is hitting elements of the array that were never initialised. Try this:
while( pos < 49 && inFile >> x[pos] )
{
pos++;
}
x[pos] = '\0';
Note that pos after the loop will now be the same as what is returned by strlen(x).
If you don't need a null-terminated string, then just use pos instead of strlen(x) without terminating but in that case you will need to avoid using any string functions that rely on null-terminated strings.
You also have a stack-smashing problem (undefined behaviour) in your constructor:
hold::hold()
{
x[50] = NULL;
}
This is not okay. You are not allowed to modify memory past the end of the array. If you want to zero it, you can just do
memset( x, 0, sizeof(x) );
Or in C++11:
hold::hold()
: x{ 0 }
{
}
strlen expects a null-terminated string. Since your x is not null-terminated, passing it to strlen is undefined behavior.
Fortunately, you do not need to call strlen, because you have variable pos that counts the number of active entries inside x:
std::cout << "length of my string = " << pos << std::endl;
for(int i = 0; i < pos ; i++) {
std::cout << x[i] << " ";
}
Is there a way to account for that extra character other than pos-1?
Yes, a better way is to increment pos only when you know that character input has been successful:
while(inFile >> x[pos]) {
pos++;
}