I am trying to get read in some text about 100 char long or less and then strip it of spaces, digits, special char, etc.. I was thinking about ways to go about doing this but I think I must have forgotten most of what I know about cstrings and such. I was originally trying to just take in basic characters and copy them into a new string but 1. I couldn't figure out how to write it so my compiler doesn't hate me and 2. I'm pretty sure I don't want the new, stripped string to have blanks in it (I'm pretty sure my code so far would cause that to happen, if it even worked).
char * userText="";
char * justCharTxt;
cout << "Enter text: " << endl;
cin.getline(userText, STRING_SIZE);
for (int i = 0; i < strlen(userText); i++){
if (((userText[i] >= 'a') && (userText[i] <= 'z')) ||
((userText[i] >= 'A') && (userText[i] <= 'Z')))
*justCharTxt = userTxt[i];
}
Some guidance on this issue would be awesome. Thanks!
Just use a std::string, no need to fiddle around with char arrays or pointers.
#include <iostream>
#include <string>
#include <algorithm>
int main()
{
std::string line;
getline(std::cin, line);
line.erase(
std::remove_if(line.begin(), line.end(),
[](char c) {return !isalpha(c, std::locale());}),
line.end()
);
std::cout << line << '\n';
}
you need to init your strings, i.e., reserve a buffer
you need to increment the dest pointer.
#include <iostream>
using namespace std;
int main(){
int const STRING_SIZE=20;
char userText[STRING_SIZE*2]="";
char justCharTxt[STRING_SIZE]="";
char * txtPt = justCharTxt;
cout << "Enter text: " << endl;
cin.getline(userText, STRING_SIZE);
for (int i = 0; i < strlen(userText); i++){
if (((userText[i] >= 'a') && (userText[i] <= 'z')) ||
((userText[i] >= 'A') && (userText[i] <= 'Z')))
*(txtPt++)= userText[i];
}
cout << justCharTxt << endl;
return 0;
}
$ clang++ justit.cpp
$ ./a.out
Enter text:
ab123 a
aba
Your char arrays do not have enough memory, and they are const.
char userText[STRING_SIZE];
Related
The program works fine, although the fist printed number is always "3452816845". I have tried initializing "str[i]" by adding curly brackets when defining the array, or by giving it NULL value, but then the first printed number is always "zero", and only then it prints what I entered. Please take a look below:
#include <iostream>
using namespace std;
int main() {
unsigned* str = new unsigned[1000];
int cnt = 0;
char ch;
int a;
cout << "Please enter text: ";
do {
cin.get(ch);
if (ch <=57 && ch >=48) {
int a = ch - '0';
cnt++;
str[cnt] = a;
}
} while (ch != '\n');
cout << "The entered numbers are: ";
for (int i = 0; i <= cnt; i++) {
cout << str[i] << " "; // here is where the error appears
}
delete[] str;
return 0;
}
Do not using namespace std;. Especially not in headers, but try to not use it in plain .cpp files either. It's more convenient to debug code that unambiguously tells you which namespace an identifier came from right where that identifier is being used.
unsigned* str = new unsigned[1000];
Since the advent of C++11, "naked" memory allocation like that is frowned upon, and is definitely not necessary here.
You could just use a static array (unsigned str[1000];).
You could use smart pointers (auto str = std::make_unique<char[]>(1000);).
Best choice, use C++ containers, like <vector>, <string>, or (if overhead really bothers you) <array>.
if (ch <=57 && ch >=48) {
int a = ch - '0';
Do not use "magic numbers" in your code. If you want to know if the character entered is a digit, use isdigit, which is more expressive and works even for non-ASCII encodings that might have their digits at a different location in the code table.
int a = ch - '0';
This isn't wrong, as the standard guarantees this to work for digits. Note that similar arithmetic on characters (the infamous ... - 'a') is frowned upon though, and will break as soon as you leave the realm of strict ASCII-7 encoding.
cnt++;
str[cnt] = a;
C/C++ start counting at zero. You just left the first item in the array uninitialized. The beauty of the post-increment is that you can do it right there where you use the index, i.e. str[cnt++] = a;.
for (int i = 0; i <= cnt; i++)
cout << str[i] << " "; // here is where the error appears
}
Very C, and also wrong. You didn't initialize str[0], so the first round through that loop accesses uninitialized memory. If you had initialized str[0] (by incrementing cnt only after using it as an index), i <= cnt would go one item beyond what you wrote into str[], again accessing uninitialized memory. A loop should run from 0 to < cnt (not <=).
If you took my earlier advice to use <vector> or <string>, there's a much better way to loop through the items stored in it, the range-for.
#include <iostream>
#include <vector>
int main()
{
char ch;
std::vector< int > digits;
std::cout << "Please enter text: ";
do
{
std::cin.get( ch );
if ( std::isdigit( ch ) )
{
digits.push_back( ch - '0' );
}
} while (ch != '\n');
std::cout << "The entered numbers are: ";
for ( auto & i : digits )
{
std::cout << i << " ";
}
std::cout << std::endl;
return 0;
}
You never initialize str[0], but you output it.
The problem is here:
...
if (ch <=57 && ch >=48) {
int a = ch - '0';
cnt++;
str[cnt] = a;
}
...
You are incrementing cnt too early, leaving str[0] uninitialized. You should do:
if (ch <=57 && ch >=48) {
int a = ch - '0';
str[cnt++] = a;
}
Also you do have a problem in your for loop; You should start from 0 till the last initialized element in the string which is at index cnt - 1. It should be like this:
for (int i = 0; i < cnt; i++) {
cout << str[i] << " ";
}
or
for (int i = 0; i <= cnt - 1; i++) {
cout << str[i] << " ";
}
As a homework exercise we were asked to use strchr to count the amount of times a single letter appears in a string of text. It needs to count upper or lower cases as equal. It was suggested we use some sort of bit operations.
I managed to get a working program.
But i would like to make the program more interactive by allowing me to use a cin to input the string instead of typing the string directly into the source code (Which was asked by the exercise).
Is it possible to do this? Or is it not possible in the way i wrote this code.
#include <iostream>
#include <cstring>
using namespace std;
int main(){
const char *C = "This is a necesarry test, needed for testing.";
char target = 'A';
const char *result = C;
const char *result2;
int count = 0;
int j[26] ={0};
//================================================================================================================================================
for(int i = 0; i <= 51; i++){
if (i == 26){
target = target + 6;
}
result2 = strchr(result, target);
while(result2 != NULL){
if (result2 != NULL){
result2 = strchr(result2+1, target);
if (i <= 25){
j[i] = j[i] +1;
}
if(i > 25){
j[i-26] = j[i-26] +1;
}
cout << target << "\t";
}
}
cout << target << endl;
target++;
}
char top = 'a';
for(int o = 0; o<= 25; o++){
cout << "________________________________\n";
cout << "|\t" << top << "\t|\t" << j[o] << "\t|" << endl;
top++;
}
cout << "________________________________\n";
}
Simply use getline() to get a string of characters from the console. Using getline you can also consider the spaces in the user input.
string input;
getline(cin, input);
Now to use this with the strchr functionn you simply have to convert this into a C Type string which can be done as follows :
input.c_str
This returns a C type string so you can put this as an arguement to the function,
You will need
#include <string>
When I print out text2 I see that it is definitely not the reverse of the string I gave it and I'm not sure why that is. When I put in "test" I get stuff like "ȍ\2200+". Can I use strncpy on char arrays? Maybe it needs to be done with a loop - not sure. Any help would be appreciated. :)
#include <iostream>
#include <string.h>
using namespace std;
int main()
{
char text[79], text2[79];
bool input = true;
while (input) {
cout << "Please give me a line of text to examine: ";
cin.getline(text, 79);
for(int i = 0; i < strlen(text); i++ )
cout << text[i];
// test to see if it is a palindrome
strncpy(text, text2, 80);
reverse(text2, text2 + strlen(text2));
printf("%s", text2); `// when I print this out I get something odd`
if (strcmp(text, text2) == 0)
cout << " is a palindrome!" << endl;
else
cout << " is not a palindrome." << endl;
if (strcmp(text, "END") == 0)
input = false;
else
cout << "\ntype END to exit the program" << endl;
} // end while loop
} // end main
It seems you're using strncpy in a wrong way: you probably want to copy text into text2, not the other way around.
There's a much simpler way to test whether a string is a palindrome, namely:
bool is_palindrome(const char* s, size_t n) {
size_t i, j;
i = 0, j = n-1;
while (i < j && s[i++] == s[j--])
;
return i >= j;
}
Why not use std::vector<char> and std::reverse from <algorithm> to handle your problem?
I would do something like below: (note that I'm using C++11 range-based for loop and auto which you can change to a regular for loop and use std::string line if you don't have a compiler supporting this).
int main()
{
cout << "Please give me a line of text to examine: ";
auto line = ""s;
getline(cin, line);
// Push back every character to the vector
vector<char> vtext;
for (const auto &elem : line)
vtext.push_back(elem);
// Create a copy of the vector<char> and reverse the copy
vector<char> vtext_reversed{vtext};
reverse(begin(vtext_reversed), end(vtext_reversed));
// Print the line reversed
cout << "\nThis is the line reversed: ";
for (const auto &elem : vtext_reversed)
cout << elem;
}
Typically you'll see this reversal technique for char*:
void reverse(char* s) {
if(!s) return;
size_t n = strlen(s);
for(size_t i = 0; i < n/2; ++i) {
char tmp = s[i];
s[i] = s[n - i - 1];
s[n - i - 1] = tmp;
}
}
This will not work, however, with non-ASCII characters. The reason is that non-ASCII characters require multiple bytes to represent.
You will need to use wide characters to handle multi-byte codepoints, but the logic should follow above.
Here is a program I made:
#include <iostream>
#include <cstring>
using namespace std;
int main() {
char frase1 [100];
char frase2 [100];
cin >> frase1;
cin >> frase2;
char * parola1 = strtok (frase1, " .");
char * parola2 = strtok (frase2, " .");
int i;
i = strspn (parola1, parola2);
int j;
j = strspn (parola2, parola1);
cout << i << " " << j;
return 0;
}
It should ask for 2 sentences that will be stored into frase1 and frase2, then two tokenizers set two pointers to the first word of their respective array, then I should get back the values i and j, wich are ints given by the strspn function.
So when the terminal shows up should be able to put, for example, "veritas omnia vincit" and "vetirsa omnia vincit" and then get 7 7 as output.
Instead, I insert the first sentence and it returns the values of the strspn between the first and the second word of the first sentence (veritas, omnia).
This is an attempt at isolating a problem showing up in a bigger program wich I'll show you right away:
#include <iostream>
#include <cstring>
using namespace std;
void eliminaVocali (char [], char []);
int controlloAnagramma (char*, char []);
bool controlloParola (char[]);
int main() {
char frase [10];
cin >> frase;
cout << "yolo1";
char fraseCorretta [100];
cout << "yolo";
eliminaVocali(frase, fraseCorretta);
if (controlloParola(fraseCorretta)) cout << "TRUE!!";
else cout << "FALSE :(";
}
void eliminaVocali (char frase [], char fraseCorretta []){
int counter = 0;
for (int i = 0; i < 100; i++){
if (frase[i] != 'a' && frase[i] != 'e' && frase[i] != 'i' && frase[i] != 'o' && frase[i] != 'u'){
fraseCorretta[counter] = frase[i];
counter++;
}
}
}
bool controlloParola (char frase []){
char * parola = strtok (frase, " .");
if (controlloAnagramma (parola, frase) > 2) return true;
while (parola != NULL){
parola = strtok(NULL, " .");
if (controlloAnagramma (parola, frase) > 2) return true;
}
return false;
}
int controlloAnagramma (char * parola, char frase []){
int counter = 0;
char * check = new char [100];
check = frase;
char * parola2 = strtok (check, " .");
if (strlen(parola) == strlen(parola2) && strlen(parola) == strspn(parola, parola2) && strlen(parola) == strspn(parola2, parola)) counter++;
while (parola2 != NULL){
parola2 = strtok (NULL, " .");
if (strlen(parola) == strlen(parola2) && strlen(parola) == strspn(parola, parola2) && strlen(parola) == strspn(parola2, parola)) counter++;}
delete[] check;
return counter;
}
This program receive a sentence, delete all the vowels from it and then check if among the words newly formed there are 2 wich one is anagram of another.
eliminaVocali delete the vowels
controlloParola takes one word of the sentence at a given time and send it to controlloAnagramma
controlloAnagramma take the word and search into the whole sentence for an anagram
This program gives
1 [main] testingstuff 93304 cygwin_exception::open_stackdumpfile:
Dumping stack trace to testingstuff.exe.stackdump
Where testingstuff is the program name.
The problem should be into controlloAnagramma, where I use strlen and strspn.
Know fact that can be useful: Neither of the 2 yolo cout into the main is ever printed.
Please note this is a didactic program, I can only use c++ with <cstring>.
The question is, why does the strspn command behave this way? It should solve the big program. Thanks in advance.
EDIT:
cin >> frase1;
cin >> frase2;
Shoud be:
cin.getline(frase1, 100);
cin.getline(frase2, 100);
As #anton-savin pointed out.
Also
check = frase;
Should be
strcpy (check, frase);
Error persist anyway.
cin >> frase1;
cin >> frase2;
operator>> reads strings word by word, so frase1 becomes "veritas" and frase2 becomes "omnia". To read the input line by line use getline:
cin.getline(frase1, 100);
cin.getline(frase2, 100);
*Hello!
I'm making program where user enters a sentence and program
prints out how many letters there are in a sentence(Capital and non-capital).
I made a program but it prints out weird results.Please help as soon as possible. :)
include <iostream>
include <string>
using namespace std;
int main()
{
string Sent;
cout << "Enter a sentence !"<<endl;
cin>>Sent;
for(int a=0;a<Sent.length();a++){
if (96<int(Sent[a])<123 || 64<int(Sent[a])<91){
cout << "this is letter"<< endl;
}else{
cout << "this is not letter"<< endl;
}
}
}
First of all you will get one and only one word. cin >> Sent won't extract the whole line. You have to use getline in order to do this.
Second, you should use isspace or isalpha instead to check whether a character is whitespace/an alphanumeric symbol.
Third, a < b < c is essentially the same as (a < b) < c, which isn't what you meant (a < b && b < c) at all.
You can do the following with std::alpha:
#include <iostream>
#include <string>
#include <cctype>
using namespace std;
int main()
{
string Sent;
cout << "Enter a sentence !"<<endl;
//cin >> Sent;
std::getline (std::cin,Sent);
int count = 0;
for(int a=0;a<Sent.length();a++){
if (isalpha(Sent[a])
{
count ++;
}
}
cout << "total number of chars " << count <<endl;
}
It is better to use getline than using cin>> if your input contains whitespace.
if (96<int(Sent[a])<123 || 64<int(Sent[a])<91){
This is wrong.You can't compare using this notation.
You must do:
if( Sent[a] > 96 && Sent[a] < 122 || ....
if (96 < Sent[a] && Sent[a]<123 || 64 < Sent[a] && Sent[a]<91)
This is what you want, because:
96<int(Sent[a])<123
Will evaluate 96<int(Sent[a]), as bool, then, will compare it (that is 0 or 1) with 123.
This line
if (96<int(Sent[a])<123 || 64<int(Sent[a])<91)
must be something like this
if ((96<int(Sent[a]) && int(Sent[a])<123) || (64<int(Sent[a]) && int(Sent[a])<91))
but I suggest using the function isalpha() defined in the cctype header file.