I am very much a beginner at C++, and I've been trying for the past 6 hours to try to figure out how to get the number of characters in a dynamic array.
This is the code I have:
using namespace std;
int array_size;
typedef char* charPtr;
charPtr a = new char[array_size];
char *p=a;
int len(char p[]) {
int count = 0;
while (*p != '\0'); {
count++;
p++;
return count;
}
}
int main() {
cout << "Type a phrase" << endl;
cin >> array_size;
cout << "Your phrase was " << len(p) << " characters long." << endl;
return 0;
}
Any help would be greatly appreciated!
You have to remove the semicolon (;) after the temination condition of your while loop. ; is the end of an statement, after that a new statment beginns. Apart from this your return statement would be inside the while loop. Remove it outside the loop. Adapt your code like this:
int len(char p[]) {
int count = 0;
while (*p != '\0')
{
count++;
p++;
}
return count;
}
Further you have to read a string from input into your dynamicly allocated array of char:
int main() {
int array_size = 100;
char *p=new char[array_size]; // allocate memory
cout << "Type a phrase" << endl;
cin >> p; // read string into allocated memory
cout << "Your phrase was " << len(p) << " characters long." << endl;
delete p; // free memory
return 0;
}
The function strlen gives you the length of a \0-terminated string.
#include <string.h>
int main() {
int array_size = 100;
char *p=new char[array_size]; // allocate memory
cout << "Type a phrase" << endl;
cin >> p; // read string into allocated memory
cout << "Your phrase was " << strlen(p) << " characters long." << endl;
delete p; // free memory
return 0;
}
But I recommend to use std::string:
#include <string>
int main() {
std::string str;
cout << "Type a phrase" << endl;
cin >> str;
cout << "Your phrase was " << str.size() << " characters long." << endl;
return 0;
}
std::string represents a sequences of characters with dynamic length.
Getting the size of dynamically allocated array
A dynamically allocated array does not have any information about its size that is available in a standards compliant way.
We are able to compute the length of C style strings since there is sentinel element, '\0', to mark the end of the string. There are no such elements for other types.
Even then, you cannot compute the size of an array of characters allocated using heap memory like you have.
Problems with posted code
You have the following lines outside all functions.
int array_size;
typedef char* charPtr;
charPtr a = new char[array_size];
char *p=a;
They are executed before anything in main gets executed. When these lines are executed, array_size gets initialized to 0. Then you allocate memory for charPtr using 0 as the value of array_size.
Function len has an error due to a typo, which could lead to either (a) a hanging program or an incorrect return value.
int len(char p[])
{
int count = 0;
while (*p != '\0');
// ^^^ The semicolon is a problem
{
count++;
p++;
return count;
}
}
If *p is not equal to '\0', the program will never get out of the while statement. It will hange.
If *p is equal to '\0', the program will get out of the while statement but it will still execute the the lines after that. As a consequence, you will end up returning 1 as the length where 0 is the right answer.
In main, you have:
cout << "Type a phrase" << endl;
cin >> array_size;
When the user sees the output, they will try to enter a phrase. However, array_size is an int. There is a mismatch between the prompt to the user and the line to read the data.
You could change it them to:
cout << "Type array size" << endl;
cin >> array_size;
cout << "Type a phrase" << endl;
That is one step better but that still does not change the fact that memory for a was allocated using a size of 0.
Using uninitialized memory
You are calling len(p) in the cout line but the elements of p have not been initialized.
It's not clear from your post what the program is supposed to do. I am guessing that you want to read a phrase from stdin and write it out to stdout. You can use the following simplified version for that.
int main()
{
std::string phrase;
cout << "Type a phrase" << endl;
// Get the entire line as a phrase.
std::getline(std::cin, phrase);
cout << "Your phrase is " << phrase << endl;
cout << "It is " << phrase.size() << " characters long." << endl;
return 0;
}
First problem: you cannot use array_size till it has been initialized.
char* a = new char [array_size]
since array_size has not been initialized and has garbage data in it, you have no idea how big that array is going to be.
that's why first you have to initialize array_size, and only after allocate your char array.
like
int array_size = 0 //no reason to have this variable as global, but that's up to you
char *a = nullptr; //same
int main()
{
cin >> array_size;
if (array_size <= 0) //make sure the input is valid and not negative
return 0;
a = new char[array_size];
//now you can work on your newly allocated array of characters
//the number of characters the array has equals to the array_size variable.
delete[] a;
return 0;
}
your len function checks for a '\0' character, but again, you have not initialized that char array either, so it contains garbage data. therefore sometimes you may get a result of len 5, 10, 502043, anything can happen really (undefined behavior).
Related
please, why this pointer array won't accept more than 5 values?
Doing excercises from Prata's C++ book, but got stuck on this.
//ex2_numrow -- showing entered numbers til zero is entered
#include <iostream>
using namespace std;
int main()
{
int n = 0;
int num = 0;
int* entered = new int[1];
do
{
cout << "Enter number: ";
cin >> num;
entered[n] = num;
cout << "Your numbers: ";
for (int i = 0; i <= n; i++)
{
cout << entered[i] << " ";
}
cout << endl << endl;
n++;
} while (num);
delete[] entered;
return 0;
}
The code int* entered = new int[1]; gives you a pointer to an array of size one!
It is very unwise (i.e., undefined behaviour) to then try to write values outside of that array. The best case is that your code will crash before it causes any serious issues.
As an aside, the set of use cases for raw pointers is fast dwindling in C++, you should generally be looking at smart pointers instead.
I say "generally" because, if your intent is to have a resizable array, even smart pointers won't help that much. What will help is a little thing I like to call std::vector :-) You should probably look into using that for your immediate purpose.
For example, this program accepts positive numbers, adding them to a vector, then printing them out:
#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers;
int num;
do {
std::cout << "Enter number: ";
std::cin >> num; // should probably check for errors in real code
if (num >= 0) {
numbers.push_back(num);
}
} while (num >= 0);
std::cout << "You entered:";
for (int num: numbers) {
std::cout << ' ' << num;
}
std::cout << '\n';
}
I am learning the basics of C++. The code is working fine as I wanted, but what I want to know is in case 2 where the function is to swap the strings, what is basically going on? Is the string at array[pos1 -1] being copied to temp and then swapped or just the addresses of the strings to be swapped are being reallocated?
#include <iostream>
using namespace std;
int main()
{
const char *array[] {"Albert",
"Newton",
"Gallilio",
"Hawking"};
cout << "What do you want to do:\n1-Display Strings\n2-Swap Positions" << endl;
unsigned short int choice{};
cin >> choice;
switch (choice)
{
case 1:
{
for (short int i = 0; i < _countof(array); i++)
{
cout << "\n" << array[i];
}
cout << endl;
break;
}
case 2:
{
short int pos1{}, pos2{};
const char *temp{ nullptr };
cout << "Whom do you want to swap? Enter two numbers when prompted: " << endl;
cout << "Swap --- "; cin >> pos1;
cout << "With --- "; cin >> pos2;
temp = array[pos1 - 1];
array[pos1 - 1] = array[pos2 - 1];
array[pos2 - 1] = temp;
cout << "\nChanged Order is";
for (short int i{} ; i < _countof(array); i++)
{
cout << "\n" << array[i];
}
cout << endl;
break;
}
default:
cout << "\a";
}
return 0;
}
Let's assume pos1 is 1 and pos2 is 2.
Then array[pos1-1] holds a pointer to a character A that is interpreted as a string of characters Albert\0 terminated by a null. Likewise array[pos2-1] holds a pointer to the string Newton\0.
When case 2 is hit, temp is initialized to hold a null pointer. Then temp is assigned to hold a copy of the pointer to Albert\0. Then array[pos1-1] is reassigned to hold a pointer to Newton\0. We then want array[pos2-1] to point to Albert\0, but the pointer value in array[pos1-1] doens't point there anymore. That's where the copy in temp comes in, because it is still a pointer to Albert\0, so this pointer is copied to array[pos2-1].
For my assignment, I have to call a function that takes the user input and spits out the number of non-whitespace characters. Inside the program, I have this code:
int GetNumOfNonWSCharacters(const string givenText) {
int counter;
for (int i = 0; i < givenText.length(); i++) {
if (givenText.at(i) != ' ') {
counter++;
}
}
return counter;
}
When I return the counter integer, this is how I output it with the string sampleText being the input:
if (menuInput == 'c' || menuInput == 'C') {
cout << "Number of whitespaces: " << GetNumOfNonWSCharacters(sampleText) << endl;
}
It returns an answer like 1231341235 or something along those lines. Now, when I type this code into a different file, pretty sure it's identical, I get the correct result every time:
int NumNonWhitespaces(const string userInput) {
int counter;
for (int i = 0; i < userInput.length(); i++) {
if (userInput.at(i) != ' ') {
counter++;
}
}
return counter;
}
int main() {
string userString;
cout << "Enter some text" << endl;
getline(cin, userString);
cout << "You entered: " << userString << endl;
cout << NumNonWhitespaces(userString);
return 0;
}
Does anyone have a solution to the problem ?
There is even more simple way to count the number of non white spaces by using the STL count algorithm:
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main() {
string userString;
cout << "Enter some text" << endl;
getline(cin, userString);
cout << "You entered: " << userString << endl;
//count the number of white spaces
int numberOfWhiteSpace = count(userString.begin(), userString.end(), ' ');
//substruct that number from the total length of your string
cout << "number of non-whitespace: " << userString.length() - numberOfWhiteSpace;
return 0;
}
But in your solution you have to initialize the variable counter to 0
If you use counter without initializing it first, you'll get whatever junk memory existed at its memory address before your program started using it (C++ does not automatically zero-out the memory when you declare a variable). The fact it works when you copy it into a new file is purely coincidental.
The fix is simply to initialize counter to 0 before using it:
int counter = 0;
In some programming languages if a variable is allocated but not assigned, it is said to have a "garbage value" , that is, some information that was being held any random piece of the computer's memory. So initialize the counter variable to 0
You have to initialise the counter variable otherwise it will contain any old value.
int counter=0;
I'm trying to use a Dynamic Array to change a lowercase word into an uppercase word. I ran into something I haven't encountered before called a "Heap Corruption". Can someone explain to me what I am doing wrong and possibly help fix this??
#include <iostream>
#include <cctype>
#include <new>
#include <string>
using namespace std;
int main()
{
int i;
int w;
char *p;
string str;
cout << "Change lowercase to UPPERCASE!" << endl;
cout << "Enter Word: ";
cin >> str;
w = str.length();
p = new (nothrow) char[w];
if (p == nullptr)
cout << "Error: memory could not be allocated" << endl;
else
{
cout << "Re-Enter Word: ";
cin >> p[w];
for (i = 0; i < w; i++)
cout << static_cast<char>(toupper(p[i]));
cout << endl;
}
delete[] p;
cout << "Press <Enter> to Exit";
cin.get();
return 0;
}
There's no need to use char* for conversion to upper case. Instead you could use std::transform like here:
transform(str.begin(), str.end(), str.begin(), ::toupper);
cout << str << endl;
--- edit ---
If, for whatever (academic) reason, you want to perform the conversion to upper case on a dynamically allocated char array, then you could still use std::transform for that.
However, as you see in the snippet below, you need to allocate one extra character for the trailing \0-char which signals end of string.
char* szStr = new char[w+1];
std::transform(str.begin(), str.end(), szStr, ::toupper);
szStr[w]='\0';
cout << szStr << endl;
you made so many mistakes, but to just answer your question:
p = new (nothrow) char[w + 1];
this is so that we will have room for the null termination character ('\0')
and also use:
cin >> p;
Had this program in C and was trying to convert some to C++ as I learn the language. Basically char arrays to strings and some of the input/output. Only issue is I get a segfault when attempting to put the input string into the string array (test2 prints. test3 does not).
Any ideas? Any bad coding habits I should be aware of as I learn c++?
int main() {
int nstr=0, nchar=0, nint=0, nfloat=0;
string input;
int i, z=0;
float inputFloat;
string *strList = (string*)malloc(sizeof(string) * nstr);
char *charList = (char*)malloc(sizeof(char) * nchar);
int *intList = (int*)malloc(sizeof(int) * nint);
float *floatList = (float*)malloc(sizeof(float) * nfloat);
while (z != -42) {
cout << "Input: ";
cin >> input;
cin.ignore();
inputFloat = strtof(input.c_str(), NULL);
if (inputFloat) {
if (fmod(inputFloat, 1.0)) {
nfloat++;
floatList = (float*)realloc(floatList, sizeof(float) * nfloat);
floatList[nfloat-1] = inputFloat;
}
else {
nint++;
intList = (int*)realloc(intList, sizeof(int) * nint);
intList[nint-1] = (int)inputFloat;
}
}
else {
if (input.length() == 1) {
nchar++;
charList = (char*)realloc(charList, sizeof(char) * nchar);
if (input.at(0) == 10)
input = " ";
charList[nchar-1] = input.at(0);
}
else {
nstr++;
cout << "test1" << endl;
strList = (string*)realloc(strList, sizeof(string) * nstr);
cout << "test2" << endl;
strList[nstr-1] = input;
cout << "test3" << endl;
}
}
cout << "Integers: ";
for (i=0; i<nint; i++)
cout << intList[i] << " ";
cout << endl << " Floats: ";
for (i=0; i<nfloat; i++)
cout << floatList[i] << " ";
cout << endl << " Chars: ";
for (i=0; i<nchar; i++)
cout << charList[i] << " ";
cout << endl << " Strings: ";
for (i=0; i<nstr; i++)
cout << strList[i] << " ";
cout << endl << endl;
}
}
As a rule you don't use malloc,calloc,realloc etc. in c++ at all, even though you can.
It less meaningful for simple items like: int, char etc. but when using on objects (like std::string) it cause this kind of problems:
When this line runs:
string *strList = (string*)malloc(sizeof(string) * nstr);
You allocate storage to array of strings, but you didn't called any constructor, therefor all the storage you've allocated is still useless.
In c++ you must use new like this:
string *strList = new string[nstr];
it is shorter, easier and call the constructor of each allocated object.
In the end you dealocate it with delete [] like this:
delete [] strList;
Even better is to use:
vector<string> strList;
and add elements by using:
strList.push_back("something"); or strList.push_back(some_string);
vectors are take care for the memory allocation and free, and are freed automatically as regular object at end of life, so it won't needed to be deleted at all.
realloc reassigns a larger array than the previous one. The new element at the end of the array, you fill it as a integer, float, char , which are basic C types. For C++ objects like strings, the last element in your array is not a new string, one of the possibilities is to create arrays of string pointers.
at the start of your code
string **strList = (string**)malloc(sizeof(string *) * nstr);
and by the end of your code, allocate a new string object at the end of the array.
nstr++;
strList = (string**)realloc(strList, sizeof(string *) * nstr);
strList[nstr-1] = new string(input);
at the end of the program you must delete everything you created through new operator and thru malloc/realloc.
while (nstr--)
{
delete strList[nstr];
}
free(strList);