C++ Char without Limit - c++

I'm pretty well versed in C#, but I decided it would be a good idea to learn C++ as well. The only thing I can't figure out is chars. I know you can use the string lib but I also want to figure out chars.
I know you can set a char with a limit like this:
#include <iostream>
using namespace std;
int main()
{
char c[128] = "limited to 128";
cout << c << endl;
system("pause");
return 0;
}
But how would I make a char without a limit? I've seen chars with * but I though that was for pointers. Any help is greatly appreciated.

You can't have an array without limit. An array occupies space in memory, and sadly there is no such thing as limitless memory.
Basically, you have to create an array of a certain size and write logic to expand the size of the array as you need more space (and possibly shrink it as you need less space).
This is what std::string and std::vector do under the hood for you.

You can use a vector of char.

std::string being a nice implementation of a vector of chars :)

A datastructure needs memory allocated for it.
Some datastructures (such as string, or a vector of chars) have internal logic in their class which allocates memory as needed dynamically.
Arrays (which come from C) do not - you need to allocate memory for them manually, by either static way (char c[128]) as your example does, or dynamically at runtime via malloc() and company. Of course, to do the dynamic allocation/reallocation right is not very simple and why bother doing it when there already are classes (e.g. string) that do it for you the right way? :)

C/C++ char arrays are just about identical to char*. The same block of code can be rewritten as:
int main()
{
char* c = "limited to 128";
cout << c << endl;
system("pause");
return 0;
}
The compiler will generate a null terminated string for you that you could use throughout your code. The way to do it dynamically would be to either use malloc or operator new [].
char* str = malloc(sieof(char) * requiredlength); //C-compatible
OR
char* str = new char[requiredlength];

Related

Is size of an array flexible in C++?

After declaring a character array, say char s[20], and eventually getting inputs using cin.getline(s,100) change the size of the array to 100, change (exactly) to the number of characters entered as input, or does it change at all? What happens to the array size that I initially declared?
I'm new to programming, so your simple explanation will be greatly appreciated. Thank you!
The size does not change what happens is that you are writing past the buffer size. If you write far enough through the buffer you will end up causing a buffer overflow.
You should use std::vector whenever you can instead of c-style arrays.
As Ted Lyngmo commented, in this case std::string will be better to use than std::vector or the c-style array:
std::string input;
std::getline(std::cin, input);
The answer is: No.
The size of the character array s doesn't changes to 100, but when you exceed the limit of the array's length, you cause a buffer overflow, which is really bad.
Let's consider an incorrect program, which is based on your assumption:
#include <iostream>
int main(void) {
char s[20];
std::cout << "Enter a sentence: ";
std::cin.getline(s, 100);
std::cout << s << std::endl;
return 0;
}
Here I just try to expand the size of array s, it actually doesn't.
If you enter an example sentence, like: hello-world-how-are-you-today (which contains 29 characters including a null-terminator), it'll just store:
hello-world-how-are-
And notice that it doesn't contains a null-terminator since all the containers are used and it just keeps reading which may cause undefined behavior (UB).
Arrays don't have dynamic memory. If you want dynamic memory allocation, you can use std::string for an array of characters, or std::vector.
std::string works like char s[x];, but it is more flexible and it has a few different things.
std::vector is basically like an array, but you can add / remove elements.
Syntax:
std::vector<type> name; // this is the classic syntax, I won't get more in-depth
Example:
std::vector<int> myVect;
You can add elements using myVect.insert(position, element); or something similar, I don't remember exactly, or you can use myVect.push_back(element); to add an element at the end of the vector.
Search it on cplusplus reference or GeeksForGeeks, you'll find a lot of information.
C++ doesn't have a variable-length array.
To handle this situation, you can have below data structures.
std::string
std::vector
dynamic array, using new[] in C++ or malloc() in C.
Click on the links, and you will find the description and usages.

What's the necessity of string in c++ while we already have char[]?

Many topics have discussed the difference between string and char[]. However, they are not clear to me to understand why we need to bring string in c++? Any insight is welcome, thanks!
char[] is C style. It is not object oriented, it forces you as the programmer to deal with implementation details (such as '\0' terminator) and rewrite standard code for handling strings every time over and over.
char[] is just an array of bytes, which can be used to store a string, but it is not a string in any meaningful way.
std::string is a class that properly represents a string and handles all string operations.
It lets you create objects and keep your code fully OOP (if that is what you want).
More importantly, it takes care of memory management for you.
Consider this simple piece of code:
// extract to string
#include <iostream>
#include <string>
main ()
{
std::string name;
std::cout << "Please, enter your name: ";
std::cin >> name;
std::cout << "Hello, " << name << "!\n";
return 0;
}
How would you write the same thing using char[]?
Assume you can not know in advance how long the name would be!
Same goes for string concatenation and other operations.
With real string represented as std::string you combine two strings with a simple += operator. One line.
If you are using char[] however, you need to do the following:
Calculate the size of the combined string + terminator character.
Allocate memory for the new combined string.
Use strncpy to copy first string to new array.
Use strncat to append second string to first string in new array.
Plus, you need to remember not to use the unsafe strcpy and strcat and to free the memory once you are done with the new string.
std::string saves you all that hassle and the many bugs you can introduce while writing it.
As noted by MSalters in a comment, strings can grow. This is, in my opinion, the strongest reason to have them in C++.
For example, the following code has a bug which may cause it to crash, or worse, to appear to work correctly:
char message[] = "Hello";
strcat(message, "World");
The same idea with std::string behaves correctly:
std::string message{"Hello"};
message += "World";
Additional benefits of std::string:
You can send it to functions by value, while char[] can only be sent by reference; this point looks rather insignificant, but it enables powerful code like std::vector<std::string> (a list of strings which you can add to)
std::string stores its length, so any operation which needs the length is more efficient
std::string works similarly to all other C++ containers (vector, etc) so if you are already familiar with containers, std::string is easy to use
std::string has overloaded comparison operators, so it's easy to use with std::map, std::sort, etc.
String class is no more than an amelioration of the char[] variable.
With strings you can achieve the same goals than the use of a char[] variable, but you won't have to matter about little tricks of char[] like pointers, segmentation faults...
This is a more convenient way to build strings, but you don't really see the "undergrounds" of the language, like how to implement concatenation or length functions...
Here is the documentation of the std::string class in C++ : C++ string documentation

Dynamically allocated strings in C

I was doing a relatively simple string problem in UVa's online judge to practice with strings since I've been having a hard time with them in C. The problem basically asks to check if a string B contains another string A if you remove the 'clutter' and concatenate the remaining characters, for example if "ABC" is contained in "AjdhfmajBsjhfhC" which in this case is true.
So, my question is how can I efficiently allocate memory for a string which I don't know its length? What I did was to make a string really big char Mstring[100000], read from input and then use strlen(Mstring) to copy the string the a properly sized char array. Something like :
char Mstring[100000];
scanf("%s",Mstring);
int length = strlen(Mstring);
char input[length+1]={0};
for(int i = 0; i<length;i++){
input[i]=Mstring[i];
}
Is there a better/standard way to do this in C? I know that C does not has a great support for strings, if there is not a better way to do it in C maybe in C++?
If you have the option of using C++ (as you mentioned), that is going to make your life a lot easier. You can then use a STL string (std::string) which manages dynamically sized strings for you. You can also drop the old scanf() beast and use std::cin.
Example:
#include <iostream>
#include <string>
void main()
{
std::string sInput;
std::getline(std::cin, sInput);
// alternatively, you could execute this line instead:
// std::cin >> sInput;
// but that will tokenize input based on whitespace, so you
// will only get one word at a time rather than an entire line
}
Describing how to manage strings that can grow dynamically in C will take considerably more explanation and care, and it sounds like you really don't need that. If so, however, here is a starting point: http://www.strchr.com/dynamic_arrays.

Read in data of a dynamic size into char*?

I was wondering how the following code works.
#include <iostream>
using namespace std;
int main()
{
char* buffer = new char(NULL);
while(true)
{
cin >> buffer;
cout << buffer;
cout << endl;
}
return 0;
}
I can input any amount of text of any size and it will print it back out to me. How does this work? Is it dynamically allocating space for me?
Also, if I enter in a space, it will print the next section of text on a new line.
This however, is fixed by using gets(buffer); (unsafe).
Also, is this code 'legal'?
It's not safe at all. It's rewriting whatever memory happens to lie after the buffer, and then reading it. The fact that this is working is coincidental. This is because your cin/cout operations don't say "oh, a pointer to one char, I should just write one char" but "oh, you have enough space allocated for me."
Improvement #1:
char* buffer = new char(10000) or simply char buffer[10000];
Now you can safely write long-ish paragraphs with no issue.
Improvement #2:
std::string buffer;
To answer your question in the comment, C++ is all for letting you make big memory mistakes. As noted in comment this is because it's a "don't pay for what you don't need" language. There are some people who really need this level of optimization in their code although you are probably not one of them.
However, it also gives you plenty of ways to do it where you don't have to think about memory at all. I will say firmly: if you are using new and delete or char[] and not because you are using a design pattern with which you've familiarized that require them, or because you are using 3rd-party or C libraries that require them, there is a safer way to do it.
Some guidelines that will save you 80% of the time:
-Don't use char[]. Use string.
-Don't use pointers to pass or return argument. Pass by reference, return by value.
-Don't use arrays (e.g. int[]). Use vectors. You still have to check your own bounds.
With just those three you'll be writing "pretty safe", non-C-like code.
This is what std::string is for:
std::string s;
while (true)
{
std::cin >> s;
std::cout << s << std::endl;
}
std::string WILL dynamically allocate space for you, so you don't have to worry about overwriting memory elsewhere.

Confusing char arrays and pointers in c++

Hey everyone, thanks for taking the time to address my problem. I've looked at so much material at this point that I've just started getting more and more confused. Basically, I'm writing a simple segment of code that parses a string. Please understand that my question is NOT about parsing. I am using C++ and have never used C before and possess a little bit of c++ experience (introductory experience, I'm still a newbie).
struct parsedString{
char chunk1[50];
char chunk2[10];
char chunk3[50];
};
main(char* bigstring)
{
parsedString ps;
ps = parseMe(bigString)
cout << ps.chunk1 << endl;
cout << ps.chunk2 << endl;
cout << ps.chunk3 << endl;
}
parsedString parseMe(char* stringToParse)
{
char* parseStr = stringToParse;
parsedString ps;
ps.chunk1 = first x chars;
ps.chunk2 = next y chars;
ps.chunk3 = last z chars;
return ps;
}
Obviously this is not working code, I didn't want to throw up all the extra stuff since it would be tougher to read through and I'm pretty sure my problem is a newbie c/c++ problem and something about memory allocation or something like that...
Basically when the main function gets to printing the strings from the parsedString it prints out exactly what I want it to, plus garbage characters. I'm entering the values for each array ps.chunk using
ps.chunk1[i] = *parseStr
since parseStr gets me each individual character. I can't figure out where the garbage characters are coming from, does it have something to do with how I am accessing the big string? Originally I used char in the struct instead of arrays and when I printed from within the parseMe() function they would come out great but they would turn into gibberish when I accessed it from the main function. Any help is appreciated, thanks so much.
If something is unclear please let me know I'll do my best to elaborate.
It's not clear why you're trying to do this with '\0' terminated
strings, when C++ has a perfectly usable string class, but
supposing some pedagogical reasons: are your strings '\0'
terminated? How do you extract and copy the first x chars into
ps.chunk1? How do you ensure that it has a '\0'?
If you really want to get exactly n characters, you have to:
assert(strlen(parseStr) >= n);
, copy them into the target (which must contain at least n+1 char's),
memcpy(ps.chunk1, parseStr, n);
, and add the final '\0':
ps.chunk1[n] = '\0';
(And, of course, advance parseStr: parseStr += n;)
Or you can simply use std::string everywhere, and write
something like:
ps.chunk1(stringToParse.substr(startPosition, length));
As pointed out by others, you should use std::string to represent strings, and save yourself all the trouble. This could look like this:
struct parsedString{
std::string chunk1;
std::string chunk2;
std::string chunk3;
};
parsedString parseMe(const std::stirng & stringToParse) {
parsedString result;
// just an example - this assigns the first two characters of stringToParse
// to chunk1
result.chunk1 = stringToParse.substr(0, 2);
// get the other chunks
return result; // return the result
}
The above code should illustrate the usage. You can find more information on std::string here.
This could be happening due to a couple of reasons.
When you declare parsedString ps; it would be good to initialize the structure and make sure that you are receiving clean memory blocks to work with.parsedString ps = {0}; Some platforms don't do this and it's up to you to zero the memory before using it.
char* strings must end with the \0 character. This character signals the end of a char*. This is mandatory! Not inserting it at the end of the string will most probably make the print operation (for instance) display contents beyond the limits of the array giving you garbage characters. This is automatically achieved by zeroing all the struct as I suggest above.