I am taking inputs in 2D-Array. i.e--
forward 50 back 20
I want to copy "forward" in simple char array[], "50" in char array[] (each string in each char array[])
I am only able to store first element in first array.
I've tried storing index of "space" and then storing the integer values until "another space "\n" found in 2d-array, but it stored only first string (forward) in all the char arrays i ran loop on...
Here's the code i was checking on.
for (int j=0; arr[1][j] != ' '; j++)
{
check[m] = arr[1][j];
m++;
}
check[m] = '\0';
int k = 0;
cout << check << endl;
if (arr[1][m] == ' ')
{
for (;arr[1][m] == ' ';)
{
m++;
cout << arr[1][m];
value[k] = arr[1][m];
k++;
}
}
value[k] = '\0';
From your comments it seems as though this might should actually be a C question and not a C++ question.
But since this is homework anyway maybe seeing a C++11 solution will get you moving in the right direction.
const char* arr[]{"forward ", "50 ", "back ", "20"};
const string check = accumulate(cbegin(arr), cend(arr), string());
After this check will contain "forward 50 back 20".
Live Example
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'm trying to make a program in C++ in which the number of mathematical signs are counted. I am using isdigit to figure this out, but when I pass the value of my string, it gives me a warning.
This is the code that I have. The line digito[i] = entrada[i] is where I think the problem lies, but I do not understand why.
cout << "Input the operation" << endl;
cin >> input;
string digit[] = { "" };
string sign[]={""};
int cn = 0, cs = 0;
for (int i = 0; i < input.size(); i++) {
if (isdigit(input[i])) {
cout << "There is a digit in position " << i << endl;
cn += 1;
digit[i] = input[i];
}
else {
cout << "There is a sign in position " << i << endl;
// sign[i] = input[i];
cs += 1;
sign[i] = input[i];
}
}
It takes me to this code as the problem:
static _CONSTEXPR17 void assign(char& _Left, const char& _Right) noexcept
{ // assign an element
_Left = _Right;
}
Those two strings are problematic. You've unnecessarily declared them as arrays with one element each, and initialized each string to empty.
string digito[] = { "" };
string signo[]={""};
Yet afterwards, you're indexing them with non-zero indices:
digito[i] = entrada[i];
This line is problematic because of two reasons; going beyond the array bounds, and incompatible types.
digito[i] is the type of std::string (because digito is std::string[]), while entrada[i] is char (assuming entrada is std::string). std::string has an overload of its operator= that allows assigning to a single character, but that's not what you want here, I assume.
As for the second problem, std::string requires you to enlarge it before you random-access it at a given index. The best way to do this in this case would be during construction, dropping the erroneous array use:
std::cin >> entrada;
std::string digito(entrada.size(), ' ');
std::string signo(entrada.size(), ' ');
That being said, I'm not sure if this code does what you want it to. Given an input string of:
2+2/3
You'll get two such strings:
digito = "2 2 3"
signo = " + / "
If your actual goal was to tokenize the input (divide into numbers and operators), a much better way would be to use either two std::vector<char>s, or, even better:
using Number = int;
enum class Operator { Plus, Minus, Div, Mul };
using Token = std::variant<Number, Operator>
using Sequence = std::vector<Token>;
A consistent, strongly-typed data model will make it much easier to write correct code that produces it and operates on the results afterwards.
Okay. I have taken a sentence and split into an array thus far with this code I found online:
string strWords[5];
short counter = 0;
for(short i =0; i<texttoChange.length();i++)
{
strWords[counter] +=texttoChange[i];
if(texttoChange[i] == ' ')
{
counter++;
}
}
for(short i=0;i<5;i++)
{
cout << strWords[i] << "(" << strWords[i].size() << ")" << endl;
}
Now I want to take strWords[i] and split that array into an array of characters or single letter string array. Is it Possible?
Assuming you need a c style array, you can do,
char *charArray = strWords[i].c_str();, you can get the size by strlen(charArray)
otherwise there is no point of converting string to char array.
I am trying to iterate through a char array using a while loop using '\0' as the terminating condition, but my problem is that its not finding the '\0' until index position 481, the array is declared as 200 long and I cant see what I am doing wrong!! I cannot use strings or any form of string functions for this before anyone asks. Can anyone help??
#include <iostream>
using namespace std;
int main()
{
char fullString[200]={'\0'}; // Declare char string of 200, containing null characters
int alphaCount = 0;
int charCount = 0;
int wordCount = 0;
cin.getline(fullString,200); //
cout << "\n\n" << fullString;
cout << "\n\n\n";
int i=0;
int i2 = 0;
while(fullString[i]!='\0'){ //iterate through array until NULL character is found
cout << "\n\nIndex pos : " << fullString[i]; //Output char at 'i' position
while(fullString[i2]!= ' '){ //while 'i' is not equal to SPACE, iterate4 through array
if(isalpha(fullString[i2])){
alphaCount++; // count if alpha character at 'i'
}
charCount++; // count all chars at 'i'
i2++;
}
if(charCount == alphaCount){ // if charCount and alphaCount are equal, word is valid
wordCount++;
}
charCount = 0; // zero charCount and alphaCount
alphaCount = 0;
i=i2;// Assign the position of 'i2' to 'i'
while(fullString[i] == 32){ //if spaces are present, iterate past them
i++;
cout << "\n\ntest1";
}
i2 = i; // assign value of 'i' to 'i2' which is the next position of a character in the array
if(fullString[i] == '\0')
{
cout << "\n\nNull Character " << endl;
cout << "found at pos: " << i << endl;
}
}
cout << "\n\ni" << i;
cout << "\n\nWord" << wordCount;
return 0;
}
As others have pointed out, your problem is with the inner loop. You test for a space character but not for NULL, so it's iterating past the end of the last word because there is no space character after the last word.
This is easily fixed by changing your while condition from this:
while(fullString[i2]!= ' ')
... to this:
while(fullString[i2] && fullString[i2]!= ' ')
This will change your inner while loop to first test for non-NULL, and then test for non-space.
I'm not correcting the rest of your code because I presume this is a class project (it looks like one) so I'm limiting my answer to the scope of your question.
You do not check in the inner loop
while(fullString[i2]!= ' '){ //while 'i' is not equal to SPACE, iterate4 through array
if(isalpha(fullString[i2])){
alphaCount++; // count if alpha character at 'i'
}
charCount++; // count all chars at 'i'
i2++;
}
...
i=i2;// Assign the position of 'i2' to 'i'
whether the next character is equal to '\0'
It's because the inner loops don't check for the termination, they just continue looping even past the end of the string.
By the way, if you want to count the number of words, spaces and non-space characters, there are easier ways in C++. See e.g. std::count and std::count_if for the spaces and characters. For example:
std::string input = "Some string\twith multiple\nspaces in it.";
int num_spaces = std::count_if(std::begin(input), std::end(input),
[](const char& ch){ return std::isspace(ch); });
For counting words, you can use std::istringstream, std::vector, std::copy, std::istream_iterator and std::back_inserter:
std::istringstream iss(input);
std::vector<std::string> words;
std::copy(std::istream_iterator<std::string>(iss),
std::istream_iterator<std::string>(),
std::back_inserter(words));
After the code above, the size of the words vector is the number of words.
If you use e.g. std::copy_if then you can use the above code for the other cases as well (but std::count_if is better for single character classes).
So I am trying to delete duplicate chars in a partially filled array. The array is populated from a file located on my PC. My array population method is working fine; however, my duplicate deleting method is not. Here is my method:
void deleteRepeated(char array[], int* numberUsed)
{
for (int x = 0; x < *numberUsed ; x++)
{
cout << "Positions used: " << *numberUsed << endl;
for (int y = x+1; y < *numberUsed; y++ )
{
cout << "Positions used: " << *numberUsed << endl;
if (array[y] == array[x])
{
cout << "Positions used: " << *numberUsed << endl;
for (int z = y; z < *numberUsed; z++)
array[z] = array[z+1];
y--;
*numberUsed--;
cout << "Positions used: " << *numberUsed << endl;
}
}
}
}
I am passing the entire array, and the number of indices used in that array. The array length is 10, and my tests, I am using 6 out of those 10 with the chars: {'g', 'g', 'n', 'o', 'r', 'e'}. What am I doing wrong?
NOTE: "cout << "Positions used: " << *numberUsed << endl" is being used to check if the method is correctly deleting or not. In the most inner loop where index is z, is where the method starts to go bonkers.
Any help would be much appreciated.
(I wrote the first part of this answer before I read your comment about STL not being allowed, but I'll leave it anyways because I think it's rather neat code.)
You could use the functionality that the C++ standard library makes available to you. Use std::string instead of char arrays (that's nearly always a good idea), then you can do the following (note: C++11 only because of unordered_set and std::begin):
#include <string>
#include <unordered_set>
#include <iostream>
#include <iterator>
std::string uniquechars(const std::string& s) {
std::unordered_set<char> uniquechars(std::begin(s), std::end(s));
std::string newstring(std::begin(uniquechars), std::end(uniquechars));
return newstring;
}
int main() {
std::string teststr("thisisanexamplesentence");
std::cout << "The unique characters of " << teststr << " are " << uniquechars(teststr) << std::endl;
}
Note that it doesn't keep the original order of the characters though, so if that's needed this does not work.
If you have to work without the standard library, you have to dig a bit deeper. #TimChild above already made a good start diagnosing what's wrong with your program, but there are more efficient solutions, for example keeping some kind of record of which characters you have already seen. As you're working with chars, I would consider a bit-field that can hold markers (extra overhead of 256/8=32 bytes) or if that's not too much, just a plain array of bools (extra overhead 256 bytes). As the latter is easier to implement and the code is more legible:
void deleteRepeated(char array[], int *numused) {
bool seenthischar[256] = {false};
char *readpointer = &array[0];
char *writepointer = &array[0];
int length = *numused;
for ( ;readpointer <= &array[0] + length; readpointer++) {
if (seenthischar[((unsigned char) *readpointer)]) {
*numused--;
} else {
seenthischar[((unsigned char) *readpointer)] = true;
*writepointer = *readpointer;
writepointer++;
}
}
}
This only has one loop, so it only has to go through the array once, i.e. its time complexity is linear in the length of the input array.
Every time you find a dup you reduce the number chars used
*numberUsed--;
but remember this controlling the first loop index
for (int x = 0; x < *numberUsed ; x++)
so try this
int count =*numberUsed;
for (int x = 0; x < count ; x++)
this way you visit all the original chars in the array.