As the title says I want to insert a character after another one in a char array using the C - style not by using the library string, and please avoid using buffer functions as well, only the basic ones :) .
char sentence[100],*p = NULL;
cin.get(sentence,100);
char replaceChar; // after What character should we insert
cin>>replaceChar;
char insertingChar; // the character we are inserting after the replaceChar;
cin >> insertingChar ;
p = strchr(sentence , replace);
while(p != NULL){
//and this is I could think of ...
}
So let`s say that we have this sentence : "I want apples", the replaceChar = a, and the insertingChar = '*';
The result should be: "I wa*nt a*pples" .
This will shift chars to the right, making room for insertion.
void rshift( char *s ){
int n = strlen( s);
s[ n + 1] = 0;
while( n ){
s[ n ] = s[ n-1 ];
n--;
}
}
int main(){
char *p = strchr(sentence , replace);
if( p ) {
p++; // insert after
rshift( p );
*p = insertingChar;
}
}
Related
cin.get(a, 256);
for(int i = 0; i < strlen(a); i++){
if(strchr("aeiou", a[i])){
s = 0;
strcpy(substr, empty);
isubstr = 0;
}
else{
s++;
substr[isubstr++] = a[i];
if(s > maax || s == maax){
maax = s;
memset(show, 0, 256);
strcpy(show, substr);
}
}
}
cout << show;
This is the code. It intends to find the longest substring with only consonants and if there are 2+ with the same lenght it outputs the farthest one (closer to the right)
Consider the following sequence:
jfoapwjfppawefjdsjkflwea
Splitted by vowels it wold look something like this:
jf |oa| pwjfpp |a| w |e| fjdsjkflw |ea|
Notice how "fjdsjkflw" is the largest substring without a vowel. This code outputs just that including some random numbers at the end:
fjdsjkflwê²a
Why does this happen? Why does it put NULL 3 characters beyond of what it's intended to?
For starters you should write a function that finds such a longest sequence of consonants.
You provided an incomplete code so it is difficult to analyze it. For example it is not seen where and how variables substr and empty used in this call
strcpy(substr, empty);
are defined and what are their meanings.
Also there are statements like this
memset(show, 0, 256);
that do not make a sense because for example after this statement there is the statement
strcpy(show, substr);
So the previous statement is just redundant.
Or for example it seems that one of these variables s and isubstr is also redundant.
I can suggest the following solution implemented as a function.
#include <iostream>
#include <utility>
#include <cstring>
std::pair<const char *, size_t> max_consonant_seq( const char *s )
{
const char *vowels = "aeiouAEIOU";
std::pair<const char *, size_t> p( nullptr, 0 );
do
{
size_t n = std::strcspn( s, vowels );
if ( n != 0 && !( n < p.second ) )
{
p.first = s;
p.second = n;
}
s += n;
s += std::strspn( s, vowels );
} while ( *s );
return p;
}
int main()
{
const char *s = "jfoapwjfppawefjdsjkflwea";
auto p = max_consonant_seq( s );
if ( p.second ) std::cout.write( p.first, p.second ) << '\n';
return 0;
}
The program output is
fjdsjkflw
The function returns a pair of objects. The first one specifies the starting pointer of the maximum sequence of consonants in the passed string and the second object specifies the length of the sequence.
All what you need to understand how the function works is to read the description of the two C string functions strspn and strcspn.
I'm given a string and i need to display all strings that can be formed removing one letter at a time.
For example,for "abbc" i should display "bbc"
"abc"
"abc"
and "abb"
Here is my code:
int main()
{
char s[41]="abbc",*p;
int n=strlen(s);
p=s;
int i=0;
while(i<n)
{
strcpy(p+i,p+i+1);
cout<<p<<" ";
i++;
strcpy(p,s);
}
return 0;
}
It keeps showing bbc bc bc bc as if strcpy(p,s); wasn't wrote. Why can't I give a value to the pointer p in a loop?
To output substrings of a string according to your description there is no need to change the original string.
This call
strcpy(p+i,p+i+1);
has 1) undefined behavior (because the ranges are overlapped) 2) and changes the original string.
This call
strcpy(p,s);
does not make sense because the string is copied into itself due to this assignment
p=s;
The task can be done using ordinary for-loops. For example (a C++ program)
#include <iostream>
int main()
{
const char *s = "abbc";
for ( size_t i = 0; s[i] != '\0'; i++ )
{
for ( size_t j = 0; s[j] != '\0'; j++ )
{
if ( j != i ) std::cout << s[j];
}
std::cout << '\n';
}
return 0;
}
The program output is
bbc
abc
abc
abb
Or (a C program)
#include <stdio.h>
int main(void)
{
const char *s = "abbc";
for ( size_t i = 0; s[i] != '\0'; i++ )
{
for ( size_t j = 0; s[j] != '\0'; j++ )
{
if ( j != i ) putchar( s[j] );
}
putchar( '\n' );
}
return 0;
}
Here is a pure C version. It removes the last character from the string and stores it. After that it replaces each character with the one that came after it, until all have been replaced. At the end the string will contain the substring starting at the second character.
#include <string.h>
#include <stdio.h>
int main()
{
char s[41] = "abbc";
int n;
char c, tmp;
n = strlen(s);
c = 0;
while( n > 0 )
{
n--;
tmp = c;
c = s[n];
s[n] = tmp;
printf( "%s\n", s );
}
return 0;
}
p and s is pointing to the same memory. The memory is modified at each loop, so after the first loop n is no longer valid as the length of the string.
loop 1: p & s = "abbc", i=0, n=4
p+0 points to "abbc", p+1 points to "bbc"
value of s after strcpy(p+0, P+1) is "bbc"
loop 2: p & s = "bbc", i=1, n=4
p+1 points to "bc", p+1+1 points to "c"
value of s after strcpy(p+1, P+2) is "bc"
loop 3: p & s = "bc", i=2, n=4
p+2 points to null or "", p+3 points to something after string
value of s after strcpy(p+2, p+3) is undifined but likely remaining "bc"
loop 4: nothing treally change from above as you now are outside string
void inverse(char *string)
{
int i = 0;
int j = strlen(string) - 1;
char temp;
//Inverse the order
while ( i < j )
{
temp = *( string + i );
*( string + i ) = *( string + j );
*( string + j ) = temp;
i++;
j--;
}
//Capitalize letter after space
while( *string != '\0')
{
if ( *( string ) == ' ' && *( string + 1 ) != ' ')
{
*( ++string ) = toupper( *( string ) );
}
string++;
}
}
I just want to know if there is a better way to make this output, especially produce same output with less lines of code
Some general tips to cleanup and reduce the number of lines of code:
1. Use for loops instead of while loops. This
int i = 0;
while ( i < 10 )
{
// loop body
i++;
}
is better written as
for ( int i = 0; i < 10; i++ )
{
// loop body
}
2. Declare variables when you first use them. For example, the declaration of temp can be done inside the loop.
3. Use array syntax instead of pointer arithmetic. For example, this
*( string + i ) = *( string + j );
is better written as
string[i] = string[j];
With that in mind the code to reverse the string could be written as
for ( int i = 0, j = strlen(string)-1; i < j; i++, j-- )
{
char temp = string[i];
string[i] = string[j];
string[j] = temp;
}
As mentioned in the comments, the code to capitalize the first letter of words has some issues. The algorithm in the question advances the string pointer until it points to a space character, and then capitalizes the character at address string+1.
An alternative algorithm keeps a copy of the previous character. If the previous character was a space, then the current character is capitalized. Here's an implementation of that algorithm:
for ( char oldc = ' '; *string != '\0'; string++ )
{
if ( oldc == ' ' )
*string = toupper(*string);
oldc = *string;
}
Note that this will capitalize the first character in the string, and any character that follows a space. If you specifically only want to capitalize characters that follow a space, and not the first character, then change the initialization of oldc so that is doesn't start as a space, e.g.
for ( char oldc = 'a'; *string != '\0'; string++ )
Oh, you can optimize it greatly. Let's review the logic first.
We need to have each character that follows the space be uppercased in the result string. What does that mean? That means that in the original string such characters are located before the space. Thus, we have the criteria to find those in the original string and actually make them uppercase even before swapping. This renders second loop unnessessary -- we can do all in one.
Here's the example how it can be implemented:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
void transform(char* s)
{
char temp;
char* endPtr = s + strlen(s) - 1;
while (s < endPtr)
{
/*
converting left hand part like 'c ' to 'C '
so that after swap it turns to ' C'
*/
if (!isspace(*s) && isspace(*(s + 1)))
*s = toupper(*s);
/* same to the right side */
if (isspace(*endPtr) && !isspace(*(endPtr - 1)))
*(endPtr - 1) = toupper(*(endPtr - 1));
/* swap */
temp = *s;
*s = *endPtr;
*endPtr = temp;
s++;
endPtr--;
}
}
int main(void)
{
char str[] = "this is a demo string! the one and only real demo string. crazy example ";
transform(str);
printf("'%s'\n", str);
return 0;
}
You can remove the temp variable while reversing using xor operation
int end= strlen(string)-1;
int start = 0;
while( start<end )
{
string[start] ^= string[end];
string[end] ^= string[start];
string[start]^= string[end];
++start;
--end;
}
To capitalized each letter, try with code below:
char* reversestr = *string;
while( *reversestr != '\0')
{
if (i==0 || *(reversestr - 1) ==' ' && *reversestr >= 'a' && *reversestr <= 'z')
*reversestr = toupper(*reversestr);
reversestr++;
}
I am not tested the code yet, but I think it should work.
For an assignment, I am working on creating a word shifter in C++. I have little to no experience with C++ so it has been very difficult. I think I am really close but just missing some syntax that is part of C++. Any help would be appreciated greatly.
string s = phrase;
int length = s.length();
//find length of input to create a new string
string new_phrase[length];
//create a new string that will be filled by my for loop
for (int i=0; i<length; i++)
//for loop to go through and change the letter from the original to the new and then put into a string
{
int letter = int(s[i]);
int new_phrase[i] = letter + shift;
//this is where I am coming up with an error saying that new_phrase is not initialized
if (new_phrase[i] > 122)
//make sure that it goes back to a if shifting past z
{
new_phrase[i] = new_phrase[i] - 26;
}
}
cout << new_phrase<< endl;
Considering your syntax,I wrote an example for you.Besides,it is conventional
to write comment before it's relevant code.
#include <iostream>
#include <string>
using namespace std;
int main()
{
//test value;
int shift = 3;
string s = "hello string";
//find length of input to create a new string
int length = s.length();
//create a new string.it's length is same as 's' and initialized with ' ';
string new_phrase(length, ' ');
for (int i=0; i<length; i++)
{
//no need to cast explicitly.It will be done implicitly.
int letter = s[i];
//It's assignment, not declaration
new_phrase[i] = letter + shift;
//'z' is equal to 126.but it's more readable
if (new_phrase[i] > 'z')
{
new_phrase[i] = new_phrase[i] - ('z' - 'a' + 1);
}
}
cout << new_phrase<< endl;
}
This should work.
// must be unsigned char for overflow checking to work.
char Shifter(unsigned char letter)
{
letter = letter + shift;
if (letter > 'z')
letter = letter - 26;
return letter;
}
// :
// :
string new_phrase = phrase; // mainly just allocating a string the same size.
// Step throught each char in phrase, preform Shifter on the char, then
// store the result in new_phrase.
std::transform(phrase.begin(), phrase.end(), new_phrase.begin(), Shifter);
cout << new_phrase<< endl;
UPDATE: made letter unsigned, so the overflow check works.
Try and investigate this code
#include <iostream>
#include <string>
#include <cctype>
void ShiftRight( std::string &s, std::string::size_type n )
{
if ( n >= 'Z' - 'A' + 1 ) return;
for ( char &c : s )
{
bool lower_case = std::islower( c );
c = std::toupper( c );
c = ( c + n -'A' ) % ('Z' -'A' + 1 ) + 'A';
if ( lower_case ) c = std::tolower( c );
}
}
int main()
{
std::string s( "ABCDEFGHIJKLMNOPQRSTUVWXYZ" );
std::cout << s << std::endl << std::endl;
for ( std::string::size_type i = 1; i <= 'Z' -'A' + 1; i++ )
{
std::str std::string s( "ABCDEFGHIJKLMNOPQRSTUVWXYZ" );
ShiftRight( s, i );
std::cout << s << std::endl;
}
return 0;
}
The output is
ABCDEFGHIJKLMNOPQRSTUVWXYZ
BCDEFGHIJKLMNOPQRSTUVWXYZA
CDEFGHIJKLMNOPQRSTUVWXYZAB
DEFGHIJKLMNOPQRSTUVWXYZABC
EFGHIJKLMNOPQRSTUVWXYZABCD
FGHIJKLMNOPQRSTUVWXYZABCDE
GHIJKLMNOPQRSTUVWXYZABCDEF
HIJKLMNOPQRSTUVWXYZABCDEFG
IJKLMNOPQRSTUVWXYZABCDEFGH
JKLMNOPQRSTUVWXYZABCDEFGHI
KLMNOPQRSTUVWXYZABCDEFGHIJ
LMNOPQRSTUVWXYZABCDEFGHIJK
MNOPQRSTUVWXYZABCDEFGHIJKL
NOPQRSTUVWXYZABCDEFGHIJKLM
OPQRSTUVWXYZABCDEFGHIJKLMN
PQRSTUVWXYZABCDEFGHIJKLMNO
QRSTUVWXYZABCDEFGHIJKLMNOP
RSTUVWXYZABCDEFGHIJKLMNOPQ
STUVWXYZABCDEFGHIJKLMNOPQR
TUVWXYZABCDEFGHIJKLMNOPQRS
UVWXYZABCDEFGHIJKLMNOPQRST
VWXYZABCDEFGHIJKLMNOPQRSTU
WXYZABCDEFGHIJKLMNOPQRSTUV
XYZABCDEFGHIJKLMNOPQRSTUVW
YZABCDEFGHIJKLMNOPQRSTUVWX
ZABCDEFGHIJKLMNOPQRSTUVWXY
ABCDEFGHIJKLMNOPQRSTUVWXYZ
As for your code then it of course is wrong. You have not to define an array of strings. And do not use magic numbers as for example 122.
Also you may include in my code a check that a next symbol is an alpha symbol.
I created a program in C++ that remove commas (,) from a given integer. i.e. 2,00,00 would return 20000. I am not using any new space. Here is the program I created:
void removeCommas(string& str1, int len)
{
int j = 0;
for (int i = 0; i < len; i++)
{
if (str1[i] == ',')
{
continue;
}
else
{
str1[j] = str1[i];
j++;
}
}
str1[j] = '\0';
}
void main()
{
string str1;
getline(cin, str1);
int i = str1.length();
removeCommas(str1, i);
cout << "the new string " << str1 << endl;
}
Here is the result I get:
Input : 2,000,00
String length =8
Output = 200000 0
Length = 8
My question is that why does it show the length has 8 in output and shows the rest of string when I did put a null character. It should show output as 200000 and length has 6.
Let the standard library do the work for you:
#include <algorithm>
str1.erase(std::remove(str1.begin(), str1.end(), ','), str1.end());
If you don't want to modify the original string, that's easy too:
std::string str2(str1.size(), '0');
str2.erase(std::remove_copy(str1.begin(), str1.end(), str2.begin(), ','), str2.end());
You need to do a resize instead at the end.
Contrary to popular belief an std::string CAN contain binary data including 0s. An std::string 's .size() is not related to the string containing a NULL termination.
std::string s("\0\0", 2);
assert(s.size() == 2);
The answer is probably that std::strings aren't NUL-terminated. Instead of setting the end+1'th character to '\0', you should use str.resize(new_length);.
Edit: Also consider that, if your source string has no commas in it, then your '\0' will be written one past the end of the string (which will probably just happen to work, but is incorrect).
The std::srting does not terminate with \0, you are mixing this with char* in C. So you should use resize.
The solution has already been posted by Fred L.
In a "procedural fashion" (without "algorithm")
your program would look like:
void removeStuff(string& str, char character)
{
size_t pos;
while( (pos=str.find(character)) != string::npos )
str.erase(pos, 1);
}
void main()
{
string str1;
getline(cin, str1);
removeStuff(str1, ',');
cout<<"the new string "<<str1<<endl;
}
then.
Regards
rbo
EDIT / Addendum:
In order to adress some efficiency concerns of readers,
I tried to come up with the fastest solution possible.
Of course, this should kick in on string sizes over
about 10^5 characters with some characters to-be-removed
included:
void fastRemoveStuff(string& str, char character)
{
size_t len = str.length();
char *t, *buffer = new char[len];
const char *p, *q;
t = buffer, p = q = str.data();
while( p=(const char*)memchr(q, character, len-(p-q)) ) {
memcpy(t, q, p-q);
t += p-q, q = p+1;
}
if( q-str.data() != len ) {
size_t tail = len - (q-str.data());
memcpy(t, q, tail);
t += tail;
}
str.assign(buffer, t-buffer);
delete [] buffer;
}
void main()
{
string str1 = "56,4,44,55,5,55"; // should be large, 10^6 is good
// getline(cin, str1);
cout<<"the old string " << str1 << endl;
fastRemoveStuff(str1, ',');
cout<<"the new string " << str1 << endl;
}
My own procedural version:
#include <string>
#include <cassert>
using namespace std;
string Remove( const string & s, char c ) {
string r;
r.reserve( s.size() );
for ( unsigned int i = 0; i < s.size(); i++ ) {
if ( s[i] != c ) {
r += s[i];
}
}
return r;
}
int main() {
assert( Remove( "Foo,Bar,Zod", ',' ) == "FooBarZod" );
}
Here is the program:
void main()
{
int i ;
char n[20] ;
clrscr() ;
printf("Enter a number. ") ;
gets(n) ;
printf("Number without comma is:") ;
for(i=0 ; n[i]!='\0' ; i++)
if(n[i] != ',')
putchar(n[i]) ;
getch();
}
For detailed description you can refer this blog: http://tutorialsschool.com/c-programming/c-programs/remove-comma-from-string.php
The same has been discussed in this post: How to remove commas from a string in C
Well, if youre planing to read from a file using c++. I found a method, while I dont think thats the best method though, but after I came to these forums to search for help before, I think its time to contribute with my effort aswell.
Look, here is the catch, what I'm going to present you is part of the source code of the map editor Im building on right now, that map editor obviously has the purpose to create maps for a 2D RPG game, the same style as the classic Pokemon games for example. But this code was more towards the development of the world map editor.
`int strStartPos = 0;
int strSize = 0;
int arrayPointInfoDepth = 0;
for (int x = 0; x < (m_wMapWidth / (TileSize / 2)); x++) {
for (int y = 0; y < (m_wMapHeight / (TileSize / 2)); y++) {
if (ss >> str) {
for (int strIterator = 0; strIterator < str.length(); strIterator++) {
if (str[strIterator] == ',') {`
Here we need to define the size of the string we want to extract after the previous comma and before the next comma
`strSize = strIterator - strStartPos;`
And here, we do the actual transformation, we give to the vector that is a 3D vector btw the string we want to extract at that moment
`m_wMapPointInfo[x][y][arrayPointInfoDepth] = str.substr(strStartPos, strSize);`
And here, we just define that starting position for the next small piece of the string we want to extract, so the +1 means that after the comma we just passed
strStartPos = strIterator + 1;
Here, well since my vector has only 6 postions that is defined by WorldMapPointInfos we need to increment the third dimension of the array and finally do a check point where if the info has arrived the number 6 then break the loop
arrayPointInfoDepth++;
if (arrayPointInfoDepth == WorldMapPointInfos) {
strStartPos = 0;
arrayPointInfoDepth = 0;
break;
}
}
}
}
}
}
Either way on my code, think abt that the vector is just a string, thats all you need to know, hope this helps though :/
Full view:
int strStartPos = 0;
int strSize = 0;
int arrayPointInfoDepth = 0;
for (int x = 0; x < (m_wMapWidth / (TileSize / 2)); x++) {
for (int y = 0; y < (m_wMapHeight / (TileSize / 2)); y++) {
if (ss >> str) {
for (int strIterator = 0; strIterator < str.length(); strIterator++) {
if (str[strIterator] == ',') {
strSize = strIterator - strStartPos;
m_wMapPointInfo[x][y][arrayPointInfoDepth] = str.substr(strStartPos, strSize);
strStartPos = strIterator + 1;
arrayPointInfoDepth++;
if (arrayPointInfoDepth == WorldMapPointInfos) {
strStartPos = 0;
arrayPointInfoDepth = 0;
break;
}
}
}
}
}
}