I'm a beginning student of C++ and i encountered a problem with the following code:
I'm trying to concatenate a 'new line' or "\n" to a string in a matrix of char.
So far I managed to concatenate a " " char but the char "\n" or just typing multiple " " won't work.
The actual sample is getting 3 strings in const value of 10 (max chars) for each of the 3 matrix's I defined-assigning values to the first two and using a function to 'change' the third and printing it.
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
const int LINES = 3;
const int MAXCHARS = 10; //TO DO: change to 81 for final version
void cpyAndCat(char[][MAXCHARS], char[][MAXCHARS], char[][MAXCHARS], int);
void main()
{
char text1[LINES][MAXCHARS], text2[LINES][MAXCHARS], text3[LINES][MAXCHARS];
cout << "Enter " << LINES << " lines into text1:\n";
for (int i = 0; i < LINES; i++) // assign the matrix of chars text1 with strings
{
_flushall();
cin.getline(text1[i], MAXCHARS);
}
cout << "Enter " << LINES << " lines into text2: \n";
for (int i = 0; i < LINES; i++) // assign the matrix of chars text2 with strings
{
_flushall();
cin.getline(text2[i], MAXCHARS);
}
//TO DO: call the function which will recieve text1 and text2
//and put blank line(line too long) or copied line from text1 and catanted line form text2.(long correct size)
cpyAndCat(text1, text2, text3, LINES);
cout << "============================================================\n";
for (int i = 0; i < LINES; i++) // print third matrix of chars, prints 3 lines of either text or '\n'
{
_flushall();
cout << text3[i];
cout << endl;
}
system("pause");
}
void cpyAndCat(char text1[][MAXCHARS], char text2[][MAXCHARS], char text3[][MAXCHARS], int lines)
{
for (int i = 0; i < lines; i++) // searches if length of string from first 2 matrix is valid
{
if (strlen(text1[i]) + strlen(text2[i]) < MAXCHARS) // if so, copy the first to the third and catanate the second to the third
{
strcpy_s(text3[i], text1[i]);
strcat_s(text3[i], text2[i]);
}
else // if else (: , catanate 'new line' to the third matrix
{
strcat_s(text3[i], "\n"); // not working
}
cout << endl;
}
}
strcat_s and strcpy_s need three parameters, not two. I'm suprised you have anything compiling at all.
Also, you strcat onto text3 without ever initializing it. So that's probably undefined behaviour...
strcat_s takes 3 arguments, you are missing the size in bytes, also, the string was never initialized.
You would want to copy into the string and afterwards, if needed, concatenate.
Don't forget to take into account the '\0' at the end of every string.
strcpy_s(text3[i], 2, "\n");
Related
I'm trying to reverse a string in my C++ code line below revStr.at(j) = str.at(size);
But it doesn't change any of the elements in revStr.
Is there another way to do it without using any libraries.
#include <iostream>
#include<sstream>
#include <iterator>
using namespace std;
int main() {
ostringstream d;
long long c = 123456789;
d << c;
//cout << c << endl;
string str = d.str();
//cout << str.at(0) << endl;
int size = str.size() - 1;
//cout << size << endl;
ostringstream e;
e << str;
string revStr = e.str();
for (int i = size; size==0; size--) {
//cout << str.at(size);
int j = 0;
revStr.at(j) = str.at(size);
j++;
} // End For
cout << "Original String is :" << str << endl;
cout << "Reversed String is :" << revStr << endl;
}
Use std::reverse:
#include <string>
#include <algorithm>
#include <iostream>
int main()
{
std::string test{"Hello"};
std::cout << "Original string: " << test << std::endl;
std::reverse(test.begin(), test.end());
std::cout << "Reversed string: " << test << std::endl;
return 0;
}
Output:
Original string: Hello
Reversed string: olleH
If you just want to reverse a string, you should use std::reverse, as described by Tyler Lewis. It is the best option.
If you want to learn C++, then writing your own version is good practice.
The line
for (int i = size; size==0; size--)
means “Create a new int called i and set it to size initially. Then, while size is zero, do the following and then decrement size”.
There are three problems with this:
Size is not zero unless you entered a one-character string
Since you never use i, there’s no point in declaring it
Inside the loop you use j which is set to zero each time.
You can fix the first by changing the middle part of the for loop to size >= 0 (but be careful—if you later change it so that size is an unsigned type, because it doesn’t make sense for it to be negative, that code won’t work; it’s generally better to increment going up instead). You can fix the second by using i everywhere in the loop statement, and not changing size. You can fix the third by using i in the loop body, and not declaring a new variable inside the loop.
I noticed you used std::string so I used std function swap and string. Depending on if you consider this as a 'library'. There are several definitions of 'reverse'. You could reverse the word order in a string, or a pure char to char reversal like I wrote. Reversal could also mean changing character case, etc... but this is simply swap first and last. Then swap the 2nd and 2nd to last, then swap the 3rd and 3rd to last, etc...
So some points from your code. You only need to loop half the string length. The swap is from the ith and the ith to last. So the last is numCharacters - 1, thus the ith to last would be Last - i or numCharacters - 1 - i. I believe this is what you intended by using a farLeft(i) and a farRight(j) index.
#include <iostream>
void reverseStringInPlace(std::string &stringToReverse)
{
int numCharacters = stringToReverse.length();
for (int i=0; i<numCharacters/2; i++)
{ std::swap(stringToReverse[i], stringToReverse[numCharacters-i-1]); }
}
int main()
{
std::string stringToReverse = "reversing a string";
std::cout << stringToReverse << std::endl;
reverseStringInPlace(stringToReverse);
std::cout << stringToReverse << std::endl;
return 0;
}
Output:
reversing a string
gnirts a gnisrever
Changes made to the piece of code in question, it works.
for (unsigned int i = size; size >= 0; size--) {
revStr[j] = str[size];
j++;
}
I need to write a program that prompts the user to input a string, then determine the middle of the string, and generate a new string which swaps the two halves of the string and then output the results.
So far I have
int main(void) {
char *string = NULL;
char temp[1000];
cout << "Please enter a string" << endl;
cin.getline(temp, 999);
int length = strlen(temp);
string = new char[length];
strcpy(string,temp);
length = length / 2;
return EXIT_SUCCESS;
}
Which takes in the string and stores it. I just need a way to move that second half to a new array and I know I need to use strcpy() but I don't know how to properly reference that portion of the array.
Since this is C++ I'm going to suggest a standard library algorithm. You're asking to swap two halves of a sequence and std::rotate does just that. Unfortunately it does the rotation in-place and you want the result in a different string.
You could copy the string and then do the rotation but there is a std::rotate_copy algorithm that will do both (and faster than separate copy/rotate steps).
Example with char arrays:
#include <algorithm>
#include <cstring>
#include <iostream>
int main()
{
char text[1000], result[1000];
std::cout << "Please enter a string\n";
std::cin.getline(text, 999);
size_t length = strlen(text);
std::rotate_copy(text, text + length / 2, text + length, result);
result[length] = '\0';
std::cout << text << '\n' << result << '\n';
}
Example with std::string:
#include <algorithm>
#include <iostream>
#include <string>
int main()
{
std::string text, result;
std::cout << "Please enter a string\n";
std::getline(std::cin, text);
size_t length = text.size();
result.resize(length);
std::rotate_copy(text.begin(), text.begin() + length / 2, text.end(), result.begin());
std::cout << text << '\n' << result << '\n';
}
Demo on ideone.com
You could possibly use std::swap_ranges but that assumes both ranges are the same size.
if you are trying to use C, use strncpy. However, I recommend using C++ std::string and using the std::string.substr() and concatenation. The latter would be easier at least to me.
You were half way through the solution. Here I finished it using strncpy to get the first half and pointer incrementation to get the second one.
#include <iostream>
#include <cstring>
#include <cstdlib>
using namespace std;
int main(void)
{
char temp[1000];
cout << "Please enter a string" << endl;
cin.getline(temp, 999);
int length = strlen(temp);
char firstHalf[512];
strncpy (firstHalf, temp, length/2);
cout << "firstHalf: " << firstHalf << endl;
char* secondHalf = temp + length/2;
cout << "secondHalf: " << secondHalf << endl;
char* swapped_str = strcat(secondHalf, firstHalf);
cout << "Swapped string: " << swapped_str << endl;
return EXIT_SUCCESS;
}
std::string text(whatever...);
int sz = text.size() / 2;
for (int i = 0; i < sz; ++i)
std::swap(text[i], text[sz + i]);
This might be off by one when text.size() is odd.
This is a snippet of my code:
#include <iostream>
#include <fstream>
#include <string>
#include <stdlib.h> // atoi()
int main() {
std::string line;
std::ifstream numbers("numbertest.txt");
if (numbers.is_open()) {
while (std::getline(numbers, line)) {
for (int i = 0; i < line.length() - 4; i++) {
for (int n = 0; n < 5; n++) {
std::cout << atoi((line.substr(i, 5)[n]).c_str());
}
I want to operate with numbers in groups of 5, from a file. Why is atoi() not working here? It says "expression must have class type" under the second parentheses on the atoi line.
line.substr(i, 5) creates a temporary std::string containing 5 characters in line from position i
std::string foo = "hello world";
int i = 2;
std::cout << foo.substr(2, 5) << '\n';
would print "llo wo".
The [n] operator returns the nth character of the substring, which is of type char, you are then calling .c_str() on that character rather than on the substring.
You can avoid the .c_str() entirely by using std::stoi, e.g.
std::cout << "line.substr(i, 5) = " << line.substr(i, 5) << '\n';
std::cout << std::stoi(line.substr(i, 5));
aoti and stoi both take a string representation of a number as their input and return the numeric value. For example:
std::string input = "123a";
// std::cout << input * 10 << '\n'; // illegal: input is a string, not a number.
int i = std::stoi(input); // converts to integer representation, i.e. 123
std::cout << i * 10 << '\n'; // outputs 1230
----- EDIT -----
You're actually asking all the wrong questions. What you want to do is take an input pattern and output all of the patterns of 5 characters in it.
Example input: "1020304050"
Example output: 10203 02030 20304 03040 30405 04050
You don't need to convert these to numbers to output them, you can just output the characters. The problem with your original code wasn't the conversion it was the incorrect sequence of operators.
std::substring is expensive, it has to create a new, temporary string, copy characters from the original into it, and then return it, and it does it for every call.
The following should achieve what you're trying to do:
while (std::getline(numbers, line)) {
for (size_t i = 0; i < line.length() - 4; i++) {
for (size_t n = 0; n < 5; n++) {
std::cout << line[i + n];
}
std::cout << '\n';
}
}
If you really want to invoke substr, you could also implement this as
while (std::getline(numbers, line)) {
for (size_t i = 0; i < line.length() - 4; i++) {
std::cout << line.substr(i, 5) << '\n';
}
}
Here's a working demonstration: http://ideone.com/mXv2z5
Try atoi( line.substr(i,5).c_str() )
Or if you want for each character
std::cout << ((line.substr(i, 5)[n]) - '0');
Or even better
std::cout << (line[i+n]) - '0');
Note that: atoi is not ascii to integer. It converts a ctype string to number. For a single character, this conversion should be done using arithmetic or lookup table.
Also there is no point converting characters to integer and then print it (back to chacters). You should better print digit character itself.
Moreover in C++, I would prefer to use stringstream instead or atoi. On C++11 there are even more advanced solutions like sto*.
I want to make a program that will read some number in string format and output it like this: if the number is 12345 it should then output 12 23 34 45 . I tried using the substr() function from the c++ string library, but it gives me strange results - it outputs 1 23 345 45 instead of the expected result. Why ?
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
int main(void)
{
string a;
cin >> a;
string b;
int c;
for(int i=0;i<a.size()-1;++i)
{
b = a.substr(i,i+1);
c = atoi(b.c_str());
cout << c << " ";
}
cout << endl;
return 0;
}
If I am correct, the second parameter of substr() should be the length of the substring. How about
b = a.substr(i,2);
?
As shown here, the second argument to substr is the length, not the ending position:
string substr ( size_t pos = 0, size_t n = npos ) const;
Generate substring
Returns a string object with its contents initialized to a substring of the current object. This substring is the character sequence that starts at character position pos and has a length of n characters.
Your line b = a.substr(i,i+1); will generate, for values of i:
substr(0,1) = 1
substr(1,2) = 23
substr(2,3) = 345
substr(3,4) = 45 (since your string stops there).
What you need is b = a.substr(i,2);
You should also be aware that your output will look funny for a number like 12045. You'll get 12 20 4 45 due to the fact that you're using atoi() on the string section and outputting that integer. You might want to try just outputing the string itself which will be two characters long:
b = a.substr(i,2);
cout << b << " ";
In fact, the entire thing could be more simply written as:
#include <iostream>
#include <string>
using namespace std;
int main(void) {
string a;
cin >> a;
for (int i = 0; i < a.size() - 1; i++)
cout << a.substr(i,2) << " ";
cout << endl;
return 0;
}
Another interesting variant question can be:
How would you make "12345" as "12 23 34 45" without using another string?
Will following do?
for(int i=0; i < a.size()-1; ++i)
{
//b = a.substr(i, 2);
c = atoi((a.substr(i, 2)).c_str());
cout << c << " ";
}
substr(i,j) means that you start from the index i (assuming the first index to be 0) and take next j chars.
It does not mean going up to the index j.
You can get the above output using following code in c
#include<stdio.h>
#include<conio.h>
#include<string.h>
int main()
{
char *str;
clrscr();
printf("\n Enter the string");
gets(str);
for(int i=0;i<strlen(str)-1;i++)
{
for(int j=i;j<=i+1;j++)
printf("%c",str[j]);
printf("\t");
}
getch();
return 0;
}
Possible solution without using substr()
#include<iostream>
#include<string>
using namespace std;
int main() {
string c="12345";
int p=0;
for(int i=0;i<c.length();i++) {
cout<<c[i];
p++;
if (p % 2 == 0 && i != c.length()-1) {
cout<<" "<<c[i];
p++;
}
}
}
Possible solution with string_view
void do_it_with_string_view( void )
{
std::string a { "12345" };
for ( std::string_view v { a }; v.size() - 1; v.remove_prefix( 1 ) )
std::cout << v.substr( 0, 2 ) << " ";
std::cout << std::endl;
}
The string constructor can be used to get a copy of a substring.
string(const string& str, size_t pos, size_t n)
For example...
b = string(a, i, 2); // substring of a from position i, including 2 characters
This differs from substr in that the length n cannot be omitted. I offer this only as an alternative, not as an improvement.
I'm working on a small little thing here for school. After hours of researching, and a ton of errors and logic reworking I've almost completed my little program here.
I'm trying to take user input, store it into the string, get a character array from the string ( dont ask why, I just have to put this into a character array ), then get the reversed order of the phrase that the user entered. Here is my code:
#include "stdafx.h"
#include <iostream>
#include <String>
#include <cstring>
using namespace std;
using namespace System;
#pragma hdrstop
char* getCharArray(string);
string reversePhrase( int, char* );
void main(void)
{
string sPhrase = "";
int sSize = 0;
string sReversed = "";
char* cPhrase = NULL;
cout << "Welcome to the You Type It & We'll Reverse it! [Version 1.0] " << endl;
cout << "This program will reverse your phrase, and count how many characters are in it!" << endl;
cout << "To begin just enter a phrase." << endl;
cout << "Enter a phrase: ";
getline( cin, sPhrase);
sSize = sPhrase.length();
cout << endl;
cPhrase = getCharArray(sPhrase);
sReversed = reversePhrase( sSize, cPhrase );
cout << sReversed;
system("pause");
}
string reversePhrase(int size , char* cPhrase)
{
string sReversed = "";
int place = size;
for ( int i = 0; i < size ; i ++ )
{
sReversed.append(1, cPhrase[place]);
cout << "Current string: " << sReversed << endl;
cout << "Current character: " << cPhrase[place] << endl;
place--;
}
return sReversed;
}
char* getCharArray(string sPhrase)
{
int size = 1;
size = sPhrase.length();
char* cArray = NULL;
cArray = new char[size];
for (int i = 0 ; i < size ; i++)
{
cArray[size] = sPhrase.at(i);
}
return cArray;
}
When I type in "ownage" into the program, this is what I get returned:
It is almost like my Character Array is getting garbage collected before it can use all of the characters. This is probably an easy fix but, I just don't see how I can get around this one.
Try rewriting getCharArray like this
char* getCharArray(string sPhrase)
{
int size = 1;
size = sPhrase.length();
char* cArray = NULL;
cArray = new char[size+1]; // NOTE
for (int i = 0 ; i < size ; i++)
{
cArray[i] = sPhrase.at(i); // NOTE
}
}
cArray[size]=0; // NOTE
return cArray;
}
Note that the assignment in the loop now uses the index variable. Also, you need to allocate one extra char in the array to set the null terminator for the string and then you need to set it at the end.
You'll also need to think about deallocating the array at some point
The bug is in this line:
cArray[size] = sPhrase.at(i);
That size should be your loop index.
You should probably look at using std::string more, and not poke around with character arrays when there's no need to.
Why use a char array at all? It's not only useless – it complicates the code substantially (the usage of your function is more difficult, and you've forgotten to free the memory allocated by new!). Why not just have the following function:
string reverse(string const& input);
(Passing the argument by const reference instead of by value saves you a copy!)
In fact, implementing the function only takes a single line using the features of the string class (one of its constructors takes two iterators):
string reverse(string const& input) {
return string(input.rbegin(), input.rend());
}
reversePhrase is also not correct. Try something like this:
string reversePhrase(int size , char* cPhrase)
{
string sReversed = "";
sReversed.resize(size);
int place = size - 1;
for ( int i = 0; i < size ; i ++ )
{
sReversed [i] = cPhrase[place];
cout << "Current string: " << sReversed << endl;
cout << "Current character: " << cPhrase[place] << endl;
place--;
}
return sReversed;
}
First, start the array with -1. After that, use a for loop with -1 and increment inside the loop. Then, you can get the first element of the array.