new programmer here starting with the basics. I need to write a code that checks for the length of a string (line) and does things with it. I'm working on getting the length correct before I start with the next part of the task.
What's happening when I run the below code is strlen(string1) seems to be defaulting to '40' no matter what I enter?
I'm not sure what's going wrong! Any help would be greatly appreciated.
#include <iostream>
#include <string.h>
#include <string>
using namespace std;
char line, just, jline;
void prompt();
int main() {
cout << "Enter a line of text: " << endl;
char string1[line];
cin >> line;
char string2[] = "1234567890123456789012345678901234567890";
line = strlen(string1);
just = strlen(string2);
cout << "Length of string is: " << strlen(string1) << endl;
if ((strlen(string1)) > (strlen(string2))) {
cout << "Error, your line must be less than 40 characters" << endl;
}
}
CodePudding user response:
There are 2 problems with your code as described below:
Problem 1
In standard C the size of an array must be a compile time constant. This means that the following is incorrect in your program:
char string1[line]; //not standard C because line is not a constant expression
Problem 2
Note that there is another problem with this. Since line
is a global variable it will be statically initialized to 0
. Thus char string1[line];
is actually equivalent to char string1[0];
.
`But from array declarators documentation:
If the expression is a constant expression, it shall have a value greater than zero.
Thus, char string1[line];
is invalid for this reason also.
Solution
Better would be to std::string
and as shown below:
#include <iostream>
#include <string>
int main() {
std::cout << "Enter a line of text: " << std::endl;
std::string inputLine;
std::getline(std::cin, inputLine);//take input from user and put it into inputLine
std::string var = "1234567890123456789012345678901234567890";
//----------------------------------------------------vvvvv----------->use size member function of std::string
std::cout << "Length of string is: " << inputLine.size() << std::endl;
if (inputLine.size() > var.size()) {
std::cout << "Error, your line must be less than 40 characters" << std::endl;
}
else
{
std::cout<<"valid input"<<std::endl;
}
}
Demo.
In the above snippet, we have used std::string::size
to know the size/length of the std::string
.
Also, the use of global variables should be avoided wherever possible. Refer to Are global variables bad?.
CodePudding user response:
As of now, your line variable is of type char. This means that it holds a single character. If you want to store a string, you can either use a fixed size array of characters (a c-style string) or a string object. In c string objects should be preferred as they offer a wide array of advantages over c-style strings including greater security and superior ease of use.
If you wanted to get the length of a user inputed string object for example, you could write something like this
#include <iostream>
#include <string>
// if you don’t want to use std:: put using namespace std; after the includes
int main(){
std::string str;
int strLength
std::cout << “Enter a Single Word: “;
std::cin >> str;
strLength = str.lenght();
std::cout << “The length of the word is “ << strLength << std::endl;
return 0;
}
If you want to get a full line of text instead, you would replace
std::cout << “Enter a Single Word: “;
std::cin >> str;
With
std::cout << “Enter a Line of text: “;
std::getline(cin, str);
You could also use a c-style string and strlen() however, it is far more difficult to do this securely and it will make it easier to cause issues by doing something like writing a string longer than the size of the fixed size array used which can cause issues as the extra data can be written to areas it should not be written to, so if your just starting out you should probably use string objects.
If you want more information on std::string, go to https://en.cppreference.com/w/cpp/string/basic_string
On why strlen is returning 40. The way strlen() works is it takes a variable called a pointer that points to the start of an array of characters and goes through an array of characters starting at the pointer and looks for a special character called the null character ‘\0’ and returns the number of characters in the array before this null character. This can cause problems if a c-style string does not end in a null character.
In the case of the code you provided, string2 contains all 40 characters inside of the “” plus the null character at the end, so when strlen() is called using string2, it counts the 40 characters before the null character.
In the case of string1, when it is created, it is created with the size equal to the value contained in the uninitialized variable line, which in this case appears to be 0. This causes string1 to be created with a size of 0 (according to the language standard this is undefined behavior but it may still “work” in some cases). Because string2 is later created in a position directly after string1 in memory, the pointer to the start of string1 created when string1 is passed into strlen points to the start of string2 causing strlen to effectively measure the length of string2 when called on string1.
Finally, as a tip. Try to avoid placing variables in the global scope (outside of functions or other encapsulating entities like classes). These global variables are at risk of being unintentionally altered by functions in ways that might cause problems in your code. It is generally better to place these variables in main and pass them to the functions you want to use them in. If you want to have the function affect these variables, you can pass them into the function as references. To do this you would place an & behind the type of the parameter of the function the variable will be passed in as, like this.
void function(std::string &str);
//… some other code
//… somewhere in main or another function
function(alteredString);
// some other code …