Here is method that replaces all spaces in a string with '%20'. It works fine in general, but complains when execution finishes with 'Run-Time Check Failure #2 - S'. Is there an issue with my for loop?
void replaceSpace(char *s) {
int spaces = 0;
for (int i = 0; i < strlen(s); i++) {
if (s[i] == ' ') {
spaces++;
}
}
// new string that includes overwriting space, and two additional chars
int newLen = strlen(s) + spaces * 2;
s[newLen] = '\0';
for (int i = strlen(s) - 1; i >= 0; i--) {
if (s[i] == ' ') {
s[newLen - 1] = '0';
s[newLen - 2] = '2';
s[newLen - 3] = '%';
newLen -= 3;
}
else {
s[newLen - 1] = s[i];
--newLen;
}
}
}
char test[] = "rep lace Spac e";
replaceSpace(test);
cout << test << endl; //rep%20lace%20Spac%20e
edit: I ran this through cpp shell and did not have any issues oddly. Ill try updating visual studio 2015, and report back.
edit2: Nope, same error.
When you define test
char test[] = "rep lace Spac e";
you define an array of exactly 16 characters (don't forget the string terminator). There is no way to expand the array, meaning you will write out of bounds of the array which leads to undefined behavior.
The solution, of course, is to use std::string instead, and append to it.
Really, this code is not necessary. Check it:
#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>
int main()
{
std::string s("rep lace Spac e");
s.erase(std::remove_if(s.begin(), s.end(), static_cast<int(*)(int)>(std::isspace)), s.end());
std::cout << s;
}
Related
my program should have store = 5 string values - Simpsun GN120, Sonic Lux10, Ultimax G42, Antalpha A200 and Nickov N230 and then make a calculation that will make code for each value. Code would take first 3 letters and 3 last letters of a value.
first code from value: Simpsun GN120
would look like this: Sim120
my biggest issue was that i couldn't make a string array as getting a length of each value in array would crash a program so for now i have made program that will do this calculation but only if string is not array if someone could give me some tips how i could improve my code to make that string in to array
#include <iostream>
using namespace std;
int main()
{
string str = "Simpsun GN120";
int i;
string productCode[5];
for (i = 0; i < str.length(); i++)
{
if (i == 0 || i == 1 || i == 2)
{
productCode[0] += str[i];
}
if (i == str.length() - 1 || i == str.length() - 2 || i == str.length() - 3)
{
productCode[0] += str[i];
}
}
cout << productCode[0];
}
It's simple using string class .Run a loop to execute
productCode[i] = str[i].substr(0, 3) + str[i].substr(str[i].length() - 3);
and your work is done.
jignatius Thank you very much for that answer!
using namespace std;
int main()
{
string str[2] = { "Simpsun GN120", "Sonic Lux10" };
int i;
string productCode[5];
for (int i = 0; i < 2; i++)
{
productCode[i] = str[i].substr(0, 3) + str[i].substr(str[i].length() - 3);
}
cout << productCode[0] << endl;
cout << productCode[1];
}
I wrote the following program to add a '*' character after every vowel in a C string
#include <iostream>
#include <string.h>
using namespace std;
int main()
{
char s[99];
cin.get(s, 99);
char aux[99];
for (int i = 0; i < strlen(s); i++)
if(strchr("aeiou", s[i])){
strcpy(aux, s + i);
strcpy(s + i + 1, aux);
s[i+1] = '*';
}
cout << s;
return 0;
}
So if I enter the word brain it will output bra*i*n and it works perfectly fine. However if I get rid of that 'aux' string and instead of doing strcpy(aux, s + i); strcpy(s + i + 1, aux); I just do strcpy(s + i + 1, s + i); my program stops working. (Infinite looping, doesn't return 0). Why is that?
This function is meant to remove all special characters, numbers, and whitespace from the char array.
// Michael E. Torres II
// Vigenere Cipher
// February 4, 2018
// C++ code to implement Vigenere Cipher
#include <iostream>
#include <string>
#include <iomanip>
#include <fstream>
#include <algorithm>
#include <cctype>
#include <iterator>
#include <sstream>
#include <functional>
using namespace std;
// This function generates the key in
// a cyclic manner until it's length isi'nt
// equal to the length of original text
string generateKey(string str, string key)
{
int x = str.size();
for (int i = 0; ; i++)
{
if (x == i)
i = 0;
if (key.size() == str.size())
break;
key.push_back(key[i]);
}
return key;
}
// This function returns the encrypted text
// generated with the help of the key
string cipherText(string str, string key)
{
string cipher_text;
for (int i = 0; i < str.size(); i++)
{
// converting in range 0-25
int x = (str[i] + key[i]) % 26;
// convert into alphabets(ASCII)
x += 'A';
cipher_text.push_back(x);
}
return cipher_text;
}
// This function decrypts the encrypted text
// and returns the original text
string originalText(string cipher_text, string key)
{
string orig_text;
for (int i = 0; i < cipher_text.size(); i++)
{
// converting in range 0-25
int x = (cipher_text[i] - key[i] + 26) % 26;
// convert into alphabets(ASCII)
x += 'A';
orig_text.push_back(x);
transform(orig_text.begin(), orig_text.end(), orig_text.begin(), ::tolower);
}
return orig_text;
}
string removeNonAlpha(char *str)
{
unsigned long i = 0;
unsigned long j = 0;
char c;
while ((c = str[i++]) != '\0')
{
if (isalpha(c)) // this is where the breakpoint is automatically placed
{
str[j++] = c;
}
}
str[j] = '\0';
return str;
}
// Driver program to test the above function
int main(int argc, char *argv[])
{
string keyword = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
stringstream ss;
char a[] = "“I think and think for months and years. Ninety-nine times, the conclusion is false. The hundredth time I am right.” – Albert Einstein “Imagination is more important than knowledge. For knowledge is limited, whereas imagination embraces the entire world, stimulating progress, giving birth to evolution.” – Albert Einstein";
int i = 0;
string str = removeNonAlpha(a);
str.append(512 - str.length(), 'X');
transform(str.begin(), str.end(), str.begin(), ::toupper);
transform(keyword.begin(), keyword.end(), keyword.begin(), ::toupper);
string key = generateKey(str, keyword);
string cipher_text = cipherText(str, key);
transform(cipher_text.begin(), cipher_text.end(), cipher_text.begin(), ::tolower);
transform(key.begin(), key.end(), key.begin(), ::tolower);
string orig = originalText(cipher_text, key);
cout << "Original/Decrypted Text : " << "\n";
for (int i = 0; i < orig.size(); i += 81)
orig.insert(i, "\n");
cout << orig;
cout << "\n\n" << "Ciphertext : " << "\n";
for (int i = 0; i < cipher_text.size(); i += 81)
cipher_text.insert(i, "\n");
cout << cipher_text;
cout << "\n\nPress ENTER key to Continue\n";
getchar();
return 0;
}
The char array works fine with this while loop, so long as there are no special characters [.,%$#!^]. As soon as there are any special characters in the char array, it gives me the debug assertion:
"Program: ...\Projects\ConsoleApplication17\Debug\ConsoleApplication17.exe
File: minkernel\crts\ucrt\src\appcrt\convert\isctype.cpp
Line: 42
Expression: c >= -1 && c <= 255
...
The program '[11048] ConsoleApplication17.exe' has exited with code 3 (0x3)."
If I run this on repl.it or cpp.sh, I get no issues though. I appreciate any help. Thank you.
It isn't done at all. It needs to be cleaned up a lot, but I'm just trying to test it as is.
see https://msdn.microsoft.com/en-us/library/xt82b8z8.aspx
isalpha expects a number between 0 and 0xFF:
The behavior of isalpha and _isalpha_l is undefined if c is not EOF or
in the range 0 through 0xFF, inclusive. When a debug CRT library is
used and c is not one of these values, the functions raise an
assertion.
You need to cast you char to an unsigned char before passing to isalpha.
Having some trouble understanding parts of the code; the output I am getting is also wrong. The problem is to replace all spaces in a string with '%20'. The full code is shown below; it compiles but doesn't run exactly as it should.
#include <iostream>
#include <string>
using namespace std;
void replaceSpaces(string str){
//Getting the length of the string, counting the number of spaces
int strLen = str.length();
int i, count = 0;
for (i = 0; i <= strLen; i++) {
if(str[i]==' ')
count++;
}
//Determining the new length needed to allocate for replacement characters '%20'
int newLength = strLen + count * 2;
str[newLength] = '\0';
for (i = strLen - 1; i >= 0; i--) {
if (str[i] == ' ') {
str[newLength - 1] = '0';
str[newLength - 2] = '2';
str[newLength - 3] = '%';
newLength = newLength - 3;
}
else {
str[newLength - 1] = str[i];
newLength = newLength -1;
}
}
cout << str <<endl;
}
int main() {
string str = "hello jellybean hello";
replaceSpaces(str);
return 0;
}
I am probably missing something obvious, but when allocating for the new string length in this line:
int newLength = strLen + count * 2;
Here we are multiplying the number of spaces by 2, but if we are trying to replace all spaces with '%20', why not multiply it by 3?
str[newLength] = '\0';
Does this line indicate that the position past the last character in the string is assigned a null space?
Am also confused about the else statement.
else {
str[newLength - 1] = str[i];
newLength = newLength -1;
}
Not sure if I completely understand the circumstance when this would be executed.
When the functions are compiled and run, if
string str = "hello jellybean hello";
the expected output would be hello%20jellybean%20hello, except the output I am getting is hello%20jellybean%20h.
In terms of time complexity, since there are two independent for loops, would the time complexity be O(n)?
I know I'm asking a lot of different questions, many thanks in advance for any answers!
This is wrong:
str[newLength] = '\0';
std::string objects maintain their NUL terminator internally based on their size. You want
str.resize(newLength);
instead.
int newLength = strLen + count * 2;
says to allocate space (later), equal to the length of the string, plus the number of whitespaces found multiplied by two, which makes sense.
For example: so glad to help, should use the slots that the whitespaces live into for the % and they will need two more slots each, for the 20 part of the replacement that will come into play.
This is WRONG:
str[newLength] = '\0';
can't you see? You access memory out of the bounds of your string. You act like you actually allocated space equal to the newLength, but you haven't that anywhere in the code yet.
Out of bounds accessing result in Undefined Behavior and that's bad.
The else statement is just for copying non-whitespace characters, but you should already given up on that code (if it's not yours) and start from scratch or/and take a sneak peak at: Encode/Decode URLs in C++.
As for the wrong result, you should know by reaching that point of that answer, that this is expected.
Trying to do the modification in place is tricky. It's much easier to create a new string:
std::string new_string;
for (int i = 0; i < str.length(); ++i) {
if (str[i] == ' ')
new_string += "%20";
else
new_string += str[i];
}
return new_string;
or, if you like range-for:
std::string new_string;
for (char ch : str) {
if (ch == ' ')
new_string += "%20";
else
new_string += ch;
}
return new_string;
You can change that string argument in function to reference, then there wont be any need for new string, at other part of the code, you can use insert function to add '2' and '0', and you only need to convert space to '&'.
void replaceSpaces(string &str) {
size_t strLen = str.length();
for (int i = 0; i < strLen; i++) {
if (str[i] == ' ') {
str[i] = '%';
str.insert(str.begin() + i + 1, '2');
str.insert(str.begin() + i + 2, '0');
strLen += 2;
}
}
}
This is easy; replace examplestring with your string in the code, and use as you would:
#include <iostream> //debug output
#include <string>
using std::string;
using std::cout;
using std::endl;
//the string to convert
string examplestring = "this is the example string for spaces into %20";
int main()
{
int countspaces = 0; //its faster to fill a known size
for (auto &x : examplestring)if (x == ' ')countspaces++; //counts spaces
string newstring; //declare new string
newstring.resize(examplestring.size() + (countspaces*3)); //pre-set size to make it run faster
int newstringiterator = 0; //keep track of new string location
//if ' '(space), place %20 in newstring and add 3 to iteration
//else just place the letter and iterate
for (int i=0;i<examplestring.size();i++)
{
if (examplestring[i] == ' ')
{
newstring.insert(newstringiterator, "%20");
newstringiterator += 3;
}
else newstring[newstringiterator++] = examplestring[i];
}
//final newstring is the original with %20 instead of spaces.
cout << newstring << endl;
system("PAUSE"); //to read console output
return 0; //return to zero
}
This will output newstring, which is the old string with '%20' instead of spaces.
I am new to C++ and I have started to work with strings recently, but I have problems with strcpy_s(). In Visual Studio if I use the old strcpy() it said that it is unsafe and after reading more on the internet and I found out why so I started to use no more the strcpy().
In strcpy(), I have to tell it the size of buffer, but with this I have problems,because if I use strlen() it said that the buffer it is too small, even if I put a=strlen(string)+1,so I found out about another one called size_t(),and now I have no more problems with the error related to the buffer, but I got another error.
Error Link
Code:
#include <iostream>
#include <cstring>
#include <conio.h>
using namespace std;
int main()
{
int i, size_of_word;
char word[202];
cin.get(word, 201, '\n');
cin.get();
i = 0;
while (i < strlen(word) - 1)
{
if (word[i] == word[i + 1])
{
size_of_word = size_t(word + i ) + 1;
strcpy_s(word + i + 2, size_of_word, word + i);
}
else
{
i++;
}
}
cout << word;
}
As commented, prefer std::string to char arrays, they are easier to use.
If you can't use them:
strcpy_s second parameter is the size of the destination buffer, whiwh is different than the size of the string.
word buffer size is 202, so, word + i + 2 buffer size is 202-i-2, not size_of_word
size_of_word = size_t(word + i ) + 1; sets size_of_word to [address of word buffer] + i + 1 which does not make any sense...
This should work (I moved buffer size to a variable to make it easier to be changed):
#include <iostream>
#include <cstring>
#include<conio.h>
using namespace std;
int main()
{
int i;
static const size_t bufferSize = 202;
char word[bufferSize];
cin.get(word, bufferSize - 1, '\n');
cin.get();
i = 0;
while (i < strlen(word) - 1)
{
if (word[i] == word[i + 1])
{
strcpy_s(word + i + 2, bufferSize - i - 2, word + i);
}
else i++;
}
cout << word;
}