Converting String Related Function from C++ to C - c++

there is a function which I have written it myself for large numbers' Add (+) operator in C++, now I'm trying to convert it to C language but there is some problems with strings :( I tried so many things but it seems it is not working, Here is a piece of my code in C++:
#include <iostream>
#include <stdlib.h>
using namespace std;
string num1,num2,Result;
string AddF (string num1, string num2)
{
string Result;
char d;
int sum,f=0,Len1=num1.length(),Len2=num2.length();
while(Len1>=0 || Len2>=0)
{
sum=0;Len1--;Len2--;
if (Len1>=0)
sum+=num1[Len1]-'0';
if (Len2>=0)
sum+=num2[Len2]-'0';
d=((sum+f)%10)+'0';
Result=d+string(Result);
f=(sum+f)/10;
}
d=f+'0';
if (f!=0)
Result=d+string(Result);
if(Result[0]=='0')
Result.erase(0,1);
return Result;
}
int main()
{
cout << "Please Enter 1th Number: "; cin >> num1;
cout << "Please Enter 2th Number: "; cin >> num2;
Result=AddF(num1,num2);
}
Now My Converted Code in C:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *num1,*num2,*Result;
char* AddF (char *num1, char *num2)
{
char *Result,*d;
int sum,f=0,Len1=strlen(num1),Len2=strlen(num2),Temp;
while(Len1>=0 || Len2>=0)
{
sum=0;Len1--;Len2--;
if (Len1>=0)
sum+=num1[Len1]-'0';
if (Len2>=0)
sum+=num2[Len2]-'0';
Temp=((sum+f)%10);
itoa(Temp,d,10);
strcat(d,Result);
Result=d;
f=(sum+f)/10;
}
itoa(f,d,10);
if (f!=0)
{
strcat(d,Result);
Result=d;
}
if(Result[0]=='0')
memmove(&Result[0], &Result[0 + 1], strlen(Result) - 0);
return Result;
}
int main()
{
printf ("Please Enter 1th Number: "); scanf ("%s",&num1);
printf ("Please Enter 2th Number: "); scanf ("%s",&num2);
Result=AddF(num1,num2);
}
It will Crash when It reach last line.

Your code doesn't work because of several reasongs
You have to allocate d. I would recomend you declare d as an array and use the snptrinf or _snprintf functions something like
char d[32];
int x = 3;
snprintf(d, sizeof(d), "%d", x);
You have to pass an allocated memory buffer to scanf too, you can pass an array, something like
char num1[32];
char num2[32];
scanf("%31s", num1);
scanf("%31s", num2);
and the same goes for Result
You are returning an array instead of a pointer from the AddF() function, you can use a temporary array and then copy the string at the end, and return the copy, don't solve the problem using global variables.
You are assigning to Result unecessarily, if you use strcat() the destination string will be always appendend to the end of the source string.
And this will in fact be a mistake, since you declared Result as a pointer, and you are making point somewhere else, thus loosing the reference to the original pointer.
This might be what you want
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *AddF (char *number0, char *number1)
{
char *result;
int sum;
int carry;
int lengths[2];
int count;
if ((number0 == NULL) || (number1 == NULL))
return NULL;
lengths[0] = strlen(number0);
lengths[1] = strlen(number1);
result = malloc(lengths[0] + lengths[1] + 1);
if (result == NULL)
return NULL;
carry = 0;
count = 0;
while (lengths[0] >= 0 || lengths[1] >= 0)
{
lengths[0]--;
lengths[1]--;
sum = 0;
if (lengths[0] >= 0)
sum += number0[lengths[0]] - '0';
if (lengths[1] >= 0)
sum += number1[lengths[1]] - '0';
memmove(result + 1, result, ++count);
result[0] = ((sum + carry) % 10) + '0';
carry = (sum + carry) / 10;
}
result[count] = '\0';
if (result[0] == '0')
memmove(result, result + 1, count);
if (carry == 0)
return result;
memmove(result + 1, result, ++count);
result[0] = carry + '0';
result[count] = '\0';
return result;
}
int main()
{
char *numbers[2] = {NULL, NULL};
char *result;
size_t i;
for (i = 0 ; i < sizeof(numbers) / sizeof(*numbers) ; i++)
{
char chr;
size_t length;
length = 0;
printf ("Please Enter %ldth Number: ", 1 + i);
while ((chr = getchar()) != '\n')
{
char *number;
number = realloc(numbers[i], (2 + length));
if (number == NULL)
{
if (numbers[0] != NULL)
free(numbers[0]);
if (numbers[1] != NULL)
free(numbers[1]);
return -1;
}
number[length] = chr;
numbers[i] = number;
length += 1;
}
numbers[i][length] = '\0';
}
result = AddF(numbers[0], numbers[1]);
if (result != NULL)
{
printf("%s\n", result);
free(result);
}
if (numbers[0] != NULL)
free(numbers[0]);
if (numbers[1] != NULL)
free(numbers[1]);
return 0;
}

Related

Recursive program to insert a star between pair of identical characters

void pairStar(char input[]) {
int len = strlen(input);
if(input[0] == '\0'){
return ;
}
if(input[0] == input[1]){
for(int i = len; i >= 2; i--){
input[i] = input[i-1];
}
input[2] = input[1];
input[1] = '*';
}
pairStar(input+1);
}
what is the mistake in this code. I couldn't find out.
if I entered aaaa, abaa etc. it runs perfect.
but when i entered scatter is shows scat*ter?#
so what is the perfect solution ?
input string is aaaa . so output is a*a*a*a instead of a*aa*a.
You do not copy terminating character \0!
So when you have inserted a character termination of string is undefined.
Note also that proper answer for aaaa should be a*a*a*a (or a*aa*a depending on problem definition).
Split argument to define soruce and destination and use separate buffers.
void copyAddStarToPairs(const char *src, char *dst)
{
*dst = *src;
if (!*dst) return;
dst++;
char prev = *src++;
if (prev = *src) *dst++ = '*';
copyAddStarToPairs(src, dst);
}
May be you should use std::string as your char buffer may not be long enough.
#include <string>
using std::string;
void pairStar(string & s, int st) {
if (st >= (int)s.size() - 1)
return;
else if (s[st] == s[st + 1]) {
s += ' ';
for (int i = (int)s.size() - 1; i > st + 1; i--)
s[i] = s[i - 1];
s[st + 1] = '*';
st++;
}
pairStar(s, st + 1);
}
int main() {
string s = "aadqwedabbbbb*dqwdasd";
pairStar(s, 0);
cout << s << endl;
}
Add the line input[len+1]='\0'; after the lineinput[1]='*';.
What happens actually is that once you append '*',you aren't appending the '\0' character. This line will append it to the end that means string end here for the first call that you made. So recursive function will also do the same, it will add '\0' character at the end letting know that string ends here.
Consider an example:
aa is a string of length 2 and and after adding star the length of string will become 3 so input[len+1] will be input[2+1]=input[3].
So character next to the moved character will be '\0' character everytime.
PS: this is my first time adding an answer on stackoverflow...
I offer to solve this problem, using the algorithm Depth first search.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
const int maximumSize=40;
string symbols="aadqwedabbbbb*dqwdasd";
string symbolsNew;
vector<int> visited(maximumSize, 0);
template<class Type>
void showContent(Type input)
{
for(int index=0; index<input.size(); ++index)
{
cout<<input[index];
}
return;
}
void depthFirstSearch(int current, int previous)
{
if(visited[current]==1)
{
return;
}
visited[current]=1;
symbolsNew.push_back(symbols[current]);
int interactions=0;
for(int next=(current+1); next<symbols.size(); ++next)
{
if(interactions!=0)
{
break;
}
if(symbols[current]==symbols[next])
{
symbolsNew.push_back('*');
}
++interactions;
}
for(int next=current; next<symbols.size(); ++next)
{
depthFirstSearch(next, current);
}
return;
}
void solve()
{
depthFirstSearch(0, -1);
cout<<"symbols <- ";
showContent(symbols);
cout<<endl<<"symbolsNew <- ";
showContent(symbolsNew);
return;
}
int main()
{
solve();
return 0;
}
Here is the result:
symbols <- aadqwedabbbbb*dqwdasd
symbolsNew <- a*adqwedab*b*b*b*b*dqwdasd
void pairStar(char input[]) {
int len = strlen(input);
if(input[0] == '\0'){
return ;
}
if(input[0] == input[1]){
for(int i = len+1; i >= 2; i--){
input[i] = input[i-1];
}
input[2] = input[1];
input[1] = '*';
}
pairStar(input+1);
}
void helper(char input[], int start)
{
if (input[start] == '\0')
{
return;
}
helper(input, start + 1);
if (input[start] == input[start + 1])
{
for (int i = strlen(input); i >= start + 1; i--)
{
input[i + 1] = input[i];
}
input[start + 1] = '*';
}
}
void pairStar(char input[])
{
helper(input, 0);
}

Int function not returning any value

I made this function to convert a string to an integer (school assignment) and my function is not seeming to work, if it picks up any non-numeric data it should return INT_MAX. It's not returning any data no matter what, and seemingly not returning to main either.
#include <iostream>
#include <climits>
#include <string>
using namespace std;
int stringToInt(string input){
int i = 0;
if(input[i] == '-'){
i++;
//First while loop controls valid input
while(input[i] != '\0'){
if(input[i] < 49 || input [i] > 47){///Can't figure this out
return INT_MAX;
}
i++;
}
}
//Now to calculate result
int result = 0;
i = 0;
if (input[i] == '-'){
i++;
while (input[i] != '\0'){
result = (input[i] - 49) + (result * 10);
i++;
}
result = result * (-1);
return result;
}
else{
while (input[i] != '\0'){
result = (input[i] - 49) + (result * 10);
i++;
}
return result;
}
}
//////MAIN////////
int main(){
string number;
int actualNumber;
int answer;
cout << "This is my main function. Enter a string to evaluate" << endl;
getline(cin, number);
actualNumber = stringToInt(number);
cout << actualNumber;
cout << endl;
return 0;
}
Your 2nd and 3rd while loops don't increment i so you end up looping on the same number forever and never get to '\0'.
ie this one
while (input[i] != '\0'){
result = (input[i] - 48) + (result * 10);
}
i never changes.

Splitting char array into other arrays for using it later and ignoring numbers c++

So I have this assignment where you have to reposition letters in a char array by given number of repositions. The last letter must become first. For example:
Input: Hello 3
Output: lloHe
But if you have a sentence, you have to do it for each word seperately and, what is more, if there are numbers, you must ignore them. So I have trouble dealing with the check for numbers and dealing with seperate words(I use strtok to split them). This is what I have so far:
#include <iostream>
#include <cstring>
using namespace std;
void Reposition(char text[10000], int n, char result[10000])
{
int startIndex = strlen(text)-1;
int k = n-1;
int currentIndex = 0;
for(int i = 0; i < n; i++)
{
result[k] = text[startIndex];
k--;
startIndex--;
currentIndex++;
}
for(int i = 0; i <= startIndex; i++)
{
result[currentIndex] = text[i];
currentIndex++;
}
}
int main()
{
char text[10000];
cin.getline(text,10000);
int n;
cin >> n;
char result[10000];
char *words;
words = strtok(text, " .,");
while(words != NULL)
{
Reposition(text, n, result);
words = strtok(NULL, " .,");
}
for(unsigned i = 0; i <= strlen(result); i++)
cout << result[i];
return 0;
}
Use std::string instead of C-style string
To remove numbers from a string, use std::remove_if from <algorithm>:
std::string s;
. . .
s.erase(std::remove_if(s.begin(), s.end(), ::isdigit), s.end());
To reposition characters in a string, use std::rotate:
std::rotate(s.begin(), s.begin() + 1, s.end());
I did your homework.
Don't know if you are familiar with all this code.
I Also rewrote your reposition code. It looked very messy.....
One time favour from me. Try to learn something from this.
#include <iostream>
#include <cstring>
#include <ctype.h>
using namespace std;
void Reposition(char * text, int len, int n, char * result)
{
int k = n - 1;
for(int i = 0; i < len; i++)
{
result[i] = text[k++];
if(k == len) k = 0;
}
}
int main()
{
char text[10000];
cin.getline(text,10000);
int n;
cin >> n;
char result[10000];
char * word;
char * beginOfWord = text;
char * resultPointer = result;
int wordLen;
while(* beginOfWord)
{
// copy up to somthing from the alphabet
if(!isalpha(* beginOfWord))
{
*resultPointer++ = * beginOfWord++;
continue;
}
// Find the end of this word
word = strpbrk(beginOfWord, " .,0123456789");
if(word != NULL)
{
// len is distance between end of word and begin of word
wordLen = word - beginOfWord;
}
else
{
// Maybe it is the end of the string
wordLen = strlen(beginOfWord);
}
//reposition the word
Reposition(beginOfWord, wordLen, n, resultPointer);
// Move the pointers beyond the word
beginOfWord += wordLen;
resultPointer += wordLen;
}
//Always terminate
*resultPointer ='\x0';
cout << result;
return 0;
}
//reverse will reverse the string starting at position xn and ending at position (yn-1)
void reverse(char *str, int xn, int yn)
{
//positioning the pointers appropriately
char *start = str + xn;
char *end = str + yn - 1;
char temp;
while(start < end)
{
temp = *start;
*start = *end;
*end = temp;
++start;
--end;
}
}
//one of the logic to reposition
void reposition(char *str, int n)
{
int length = strlen(str);
n = (length > n) ? n : (n % length);
reverse(str, 0, n);
reverse(str, n, length);
reverse(str, 0, length);
}
int main()
{
char text[10000];
cin.getline(text,10000);
int n;
cin >> n;
char result[10000];
strcpy(result, text);
cout << "before: " << result << endl;
char *word;
word = strtok(text, " .,");
while(word != NULL)
{
//check if it is not a number
if(isdigit(word[0]) == 0)
{
reposition(word, n);
//find the word postion in text
int word_position = word - text;
//copy the repositioned word in result at its corresponding position.
int i = 0;
while(word[i])
{
result[word_position + i] = word[i];
++i;
}
}
word = strtok(NULL, " .,");
}
cout << "after : " << result << endl;
return 0;
}
Output:
abcd 345 pqrst 321
3
before: abcd 345 pqrst 321
after : dabc 345 stpqr 321

Splitting char array

I have a char **names array that basically stores names from a file.
This is my .txt file
Mike, Sam, Stuart
Andre, Williams, Phillips
Patels, Khan, Smith
Basically, I want to split and store the names before the , character.
For example, Mike, Sam, Stuart will become...
newName[0] = Mike
newName[1] = Sam
newName[2] = Stuart
I have something like this...
for (int i=0; i<3; i++)
{
for (int j=60, j>0; j--)
{
if(names[i][j] == ',')
{
cout << j << endl; //THIS PRINTS OUT THE POSITION. HOW CAN I STORE THE POSITION AND DO SOMETHING?
}
}
}
I would appreciate it if someone could help me with my code, it is in the right direction. I don't want to use any vectors classes
I have attempted to store marks of these students, however I want to add it to a double *marks[2] array.
This is my .txt file...
69.9, 56.5
29.8, 20.0
35.6, 45.0
This is my code...
char **values;
char * pch;
pch = strtok (values[i], " ,");
while (pch != NULL)
{
sscanf(pch, "%f, %f", &marks[i][0], &marks[i][1]);
pch = strtok (NULL, " ,");
}
I am getting random values such as 1.28277e-307 and 1.96471e+257
look up the strtok command it will be very helpful to you.
This code looks for hyphen characters and prints stuff... change it to commas
#include <string.h>
#include <stdio.h>
int main()
{
const char str[80] = "This is - www.tutorialspoint.com - website";
const char s[2] = "-";
char * newName[100]; /* at most 100 names */
int iCurName = 0;
char *token;
/* get the first token */
token = strtok(str, s);
/* walk through other tokens */
while( token != NULL )
{
printf( " %s\n", token );
newName[iCurName] = malloc (char *) (strlen(token) + 1);
strcpy(newName[iCurName],token);
iCurrName ++;
token = strtok(NULL, s);
}
return(0);
}
Use function strtok() to split input line into tokens; use strcpy_s() to copy each token into name buffer.
Note 1: The strtok() function replaces each separator with '\0' character, so the line variable cannot be declared with const. If your input buffer must be constant, for example if you want to use the whole line for something else, make a copy of it before calling strtok() function.
Note 2: You might want to trim space in addition to splitting your input line.
#define MAX_LINE_LENGTH 80
#define MAX_NAME_LENGTH 20
#define MAX_NAMES_PER_LINE 3
const char constInput = "Mike, Sam, Stewart";
char line[MAX_LINE_LENGTH];
strcpy_s(line, MAX_LINE_LENGTH, constInput);
char *separator = ",";
char newName[MAX_NAMES_PER_LINE][MAX_NAME_LENGTH];
int i = 0;
char *token = strtok(line, separator);
while ((i < MAX_NAMES_PER_LINE) && ((token = strtok(NULL, separator)) != NULL))
{
strcpy_s(newName[i++], MAX_NAME_LENGTH, token);
}
char newName[3][60];
for (int i=0; i<3; i++){
int r=0, c=0;
for (int j=0; j<60; j++){
if(names[i][j] == ',' || names[i][j] == '\0'){
newName[r++][c] = '\0';
c = 0;
if(names[i][j] == '\0'){
cout << newName[0] << '\n'
<< newName[1] << '\n'
<< newName[2] << '\n' << endl;
break;
}
while(names[i][++j] == ' ')
;
--j;
} else {
newName[r][c++] = names[i][j];
}
}
}
#include <fstream>
#include <iostream>
using namespace std;
int main() {
ifstream inf("data.txt");
double marks[2];
char ch;
while(inf.good()){
inf >> marks[0] >> ch >> marks[1];
cout << "mark1:" << marks[0] << endl;
cout << "mark2:" << marks[1] << endl;
}
}
I don't know if this function works fast enough, but here it is:
char** split_quotes(char *input, char separator = ' ', bool keep_quotes = false)
{
if (&input && input)
{
size_t length = strlen(input);
char **chunks = new char*[length];
bool inQuotes = false;
size_t count = 0, from = 0;
for (size_t i = 0; i < length; i++)
{
if (input[i] == '"')
{
inQuotes = !inQuotes;
}
else if (input[i] == separator && !inQuotes)
{
size_t strlen = i - from;
if (strlen > 0)
{
if (!keep_quotes && input[from] == '"' && input[i - 1] == '"')
{
from++; strlen -= 2;
}
chunks[count] = new char[strlen + 1]();
strncpy(chunks[count], &input[from], strlen);
count++;
}
from = i + 1;
}
}
if (from < length)
{
size_t strlen = length - from;
if (!keep_quotes && input[from] == L'"' && input[length - 1] == L'"')
{
from++; strlen -= 2;
}
chunks[count] = new char[strlen + 1]();
strncpy(chunks[count], &input[from], strlen);
count++;
}
// Save chunks to result array //
char **result = new char*[count + 1]();
memcpy(result, chunks, sizeof(char*) * count);
// free chunks //
delete[] chunks;
return result;
}
return NULL;
}
Usage:
wchar_t **name = split_quotes(L"Mike,Donald,\"My Angel\",Anna", L',');
if (name)
{
while (*name++)
{
std::wcout << "Person: " << *name << std::endl;
}
}

How to modify string to char array in C/C++?

i'm writing a program called 'Zuma'. The program works like this.
Input:
ACCBA // a string make up of char from 'A' to 'Z'
5 // number of inputs
1 B // insert char 'B' to position '1' of the string
0 A // and so on...
2 B
4 C
0 A
When 3 same chars next to each other, we erase/remove/delete them from the string.
For example, when we insert char 'C' to position 2 of string 'ABCC', we got 'AB' because
'CCC' are removed from the string.
Output:
ABCCBA
AABCCBA
AABBCCBA // the process is AABBCCCBA -> AABBBA -> AAA -> -
- // if the string is empty, we output "-"
A
This is my code with string:
#include <iostream>
using namespace std;
int main()
{
int n, pos;
int k = 0;
int length = 0;
string zuma, marble; // i use string
cin >> zuma;
cin >> n;
for (int i = 0; i < n; ++i)
{
cin >> pos >> marble;
zuma.insert(pos, marble);
length = zuma.length(); // length of current string
// compare each char from pos[i] with pos[i+1] and pos[i+2]
// and then ++i until end of string
while (k != length && length >= 3)
{
if (zuma[k] == zuma[k + 1] && zuma[k] == zuma[k + 2])
{
zuma.erase(k, 3); // erase 3 same char in the string
k = 0; // set k to zero to start from pos[0] again
}
else
k++;
}
// if string is not empty
if (!zuma.empty())
{
cout << zuma << endl; // output the current char in the string
k = 0;
}
else
cout << "-" << endl;
}
return 0;
}
This is my code with char array:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
void append (char subject[], const char insert[], int pos) {
char buf[100] = {};
strncpy(buf, subject, pos);
int len = strlen(buf);
strcpy(buf+len, insert);
len += strlen(insert);
strcpy(buf+len, subject+pos);
strcpy(subject, buf);
}
int main()
{
int n, pos;
int k = 0;
int length = 0;
char zuma[100], marble[100];
scanf("%s", zuma);
scanf("%d", &n);
for (int i = 0; i < n; ++i)
{
scanf("%d %s", &pos, marble);
append(zuma, marble, pos); // acts like string::insert
length = strlen(zuma);
while (k != length && length >= 3)
{
if (zuma[k] == zuma[k + 1] && zuma[k] == zuma[k + 2])
{
//zuma.erase(k, 3); // need help with this part to remove 3 same chars like string::erase
k = 0;
}
else
k++;
}
if (strlen(zuma) != 0)
{
printf("%s\n", zuma);
k = 0;
}
else
printf("%s\n","-");
}
return 0;
}
My problem is how to write a function to remove 3 same chars just like what string::erase do?
Thanks for your help!!
You can use memmove to copy the remainder of the string to the position of the characters to remove. Use strlen to determine how much bytes to move. Note you cannot use strcpy because the source and destination buffers overlap.
if (zuma[k] == zuma[k + 1] && zuma[k] == zuma[k + 2])
{
int len = strlen(zuma+k+3) + 1; // +1 to copy '\0' too
memmove(zuma+k, zuma+k+3, len);
k = 0;
}