c++: strcpy not working with char array - c++

I'm sorting an array of names and my IDE is giving me "no matching function for call to 'strcpy'.
Here are the values I set up:
char Names [MaxNames] [MaxCharsPerName + 1];
const int MaxNames (20);
const int MaxCharsPerName (15);
Here is my function
void SortNames (const char Names[][MaxCharsPerName + 1], int NumNames)
{
int i;
int NumElements;
bool Sorted;
char Temp; // size 15?
NumElements = NumNames;
do {
Sorted = true;
NumElements--;
for (i = 0; i < NumNames; i++)
{
if(Names[i-1] > Names[i]){
strcpy(Temp, Names[i]);
strcpy(Names[i], Names[i+1]);
strcpy(Names[i+1], Temp);
}
}
} while (!Sorted);
Do I have to use a reference or something?
Oh and these are at the top:
include
using namespace std;
#include "Constants.h"
#include "Functions.h"
#include <string.h>
#include <stdio.h>

char Temp; // size 15?
Temp is a char and strcpy expects a char *(and compiler will give a compilation error in your case).
Use a char array instead-
char Temp[MaxCharsPerName + 1]; // any desired size but reserve place for '\0'
And then pass it to strcpy.

Sorting an array of names could be done much easier:
vector<string> names;
// ...
sort(begin(names), end(names), less<string>());
for (const auto& name : names) cout << name << '\n';

Related

C++ Combining two zero terminated strings?

So I am doing a question where I have to join two zero terminated strings, the first contains a word, and the second is empty and twice the size of the original array. I was able to get this working using the following code
#include <stdio.h>
#include <iostream>
using namespace std;
int main()
{
char str1[] = "test";
char str2[(sizeof(str1)-1)*2];
char *p;
int count = 0;
for(p = str1; *p != 0; p++) {
str2[count] = *p;
count++;
}
cout << str2;
}
However I have to use a function with the following prototype
char *combine(char *a);
So I tried this
#include <stdio.h>
#include <iostream>
using namespace std;
char *copy_and_reverse(char *a) {
char str2[8];
int count = 0;
char* b = str2;
for(a; *a != 0; a++) {
str2[count] = *a;
count++;
}
return b;
}
int main()
{
char str1[] = "test";
char *a;
a = str1;
char* b = copy_and_reverse(a);
for(b; *b != 0; b++) {
cout << *b;
}
}
But it does not work (it is printing the string but it's printing a few random characters after it), I'm getting so confused with the pointers, can anyone help me out with this?
Edit: here is the question I am trying to answer
Write a function in C++ that takes as a char * style zero terminated string and returns a char* string twice the length of the input. The first half of the returned string should contain a copy of the contents of the original array. The second half of the string should contain the contents of the original string in reverse order.
The function should have the following prototype:
char *copy_and_reverse(char* a);
Note: you should not use any library functions (e.g from string.h).
There are two big problems in your copy_and_reverse code.
After copying the input string, you are not terminating the result. This means str2 is not a valid string. Fix:
str2[count] = '\0'; // after the loop
copy_and_reverse returns a pointer to a local variable (str2). After the function returns, all its local variables are gone, and main is dealing with an invalid pointer. To fix this, either use static memory (e.g. by declaring str2 as static or making it a global variable) or dynamic memory (allocate storage with new[] (or malloc())). Both approaches have their disadvantages.
Minor stuff:
variable; does nothing (see for (a; ...), for (b; ...)).
str2 isn't big enough for the final result. str1 is 5 bytes long ('t', 'e', 's', 't', '\0'), so char str2[8] is sufficient for now, but in the end you want to allocate length * 2 + 1 bytes for your result.
I believe that this will suit your needs:
#include <stdio.h>
#include <stdlib.h>
static char* copy_and_reverse(char* a);
static int strlen(char *c); // self-implemented
int main(void) {
char *a = "some string";
char *b = copy_and_reverse(a);
printf("%s", b);
free(b);
return 0;
}
static char* copy_and_reverse(char* a) {
int n = strlen(a);
char *b = new char[n * 2 + 1]; // get twice the length of a and one more for \0
for (int i = 0; i < n; ++i) { // does copying and reversing
b[i] = a[i];
b[i+n] = a[n-i-1];
}
b[2 * n] = '\0'; // null out last one
return b;
}
static int strlen(char *c) {
char *s = c;
while( *s++ );
return s-c-1;
}

Reverse String C++ using char array

I wrote a simple C++ program to reverse a string. I store a string in character array. To reverse a string I am using same character array and temp variable to swap the characters of an array.
#include<iostream>
#include<string>
using namespace std;
void reverseChar(char* str);
char str[50],rstr[50];
int i,n;
int main()
{
cout<<"Please Enter the String: ";
cin.getline(str,50);
reverseChar(str);
cout<<str;
return 0;
}
void reverseChar(char* str)
{
for(i=0;i<sizeof(str)/2;i++)
{
char temp=str[i];
str[i]=str[sizeof(str)-i-1];
str[sizeof(str)-i-1]=temp;
}
}
Now this method is not working and, I am getting the NULL String as result after the program execution.
So I want to know why I can't equate character array, why wouldn't this program work. And what is the solution or trick that I can use to make the same program work?
sizeof(str) does not do what you expect.
Given a char *str, sizeof(str) will not give you the length of that string. Instead, it will give you the number of bytes that a pointer occupies. You are probably looking for strlen() instead.
If we fixed that, we would have:
for(i=0;i<strlen(str)/2;i++)
{
char temp=str[i];
str[i]=str[strlen(str)-i-1];
str[strlen(str)-i-1]=temp;
}
This is C++, use std::swap()
In C++, if you want to swap the contents of two variables, use std::swap instead of the temporary variable.
So instead of:
char temp=str[i];
str[i]=str[strlen(str)-i-1];
str[strlen(str)-i-1]=temp;
You would just write:
swap(str[i], str[sizeof(str) - i - 1]);
Note how much clearer that is.
You're using C++, just use std::reverse()
std::reverse(str, str + strlen(str));
Global variables
It's extremely poor practice to make variables global if they don't need to be. In particular, I'm referring to i about this.
Executive Summary
If I was to write this function, it would look like one of the two following implementations:
void reverseChar(char* str) {
const size_t len = strlen(str);
for(size_t i=0; i<len/2; i++)
swap(str[i], str[len-i-1]);
}
void reverseChar(char* str) {
std::reverse(str, str + strlen(str));
}
When tested, both of these produce dlrow olleh on an input of hello world.
The problem is that within your function, str is not an array but a pointer. So sizeof will get you the size of the pointer, not the length of the array it points to. Also, even if it gave you the size of the array, that is not the length of the string. For this, better use strlen.
To avoid multiple calls to strlen, give the function another parameter, which tells the length:
void reverseChar(char* str, int len)
{
for(i=0; i<len/2; i++)
{
char temp=str[i];
str[i]=str[len-i-1];
str[len-i-1]=temp;
}
}
and call it with
reverseChar(str, strlen(str))
Another improvement, as mentioned in the comments, is to use std::swap in the loop body:
void reverseChar(char* str, int len)
{
for(i=0; i<len/2; i++)
{
std::swap(str[i], str[len-i-1]);
}
}
Also, there is std::reverse which does almost exactly that.
//reverse a string
#include<iostream>
using namespace std;
int strlen(char * str) {
int len = 0;
while (*str != '\0') {
len++;
str++;
}
return len;
}
void reverse(char* str, int len) {
for(int i=0; i<len/2; i++) {
char temp=str[i];
str[i]=str[len-i-1];
str[len-i-1]=temp;
}
}
int main() {
char str[100];
cin.getline(str,100);
reverse(str, strlen(str));
cout<<str<<endl;
getchar();
return 0;
}
If I were you, I would just write it like so:
int main()
{
string str;
cout << "Enter a string: " << endl;
getline(cin, str);
for (int x = str.length() - 1; x > -1; x--)
{
cout << str[x];
}
return 0;
}
This is a very simple way to do it and works great.
#include <iostream>
#include <cstdio>
using namespace std;
int main()
{
char str[80];
cout << "Enter a string bro: \n";
gets_s(str);
for (int i = strlen(str) - 1; i > -1; i--)
{
cout << str[i];
}
}

Copy from array to array by refenrence in function

I have no idea why it doesn't work. What is more I can't even say what are errors about ;/
Can any1 explain what are errors about?
The code is suposed to :
create a string with word like - mom.
then create 2d array to fill it by string. Free spaces fill with _.So mom box =
[m] [o]
[m] [_]
now fill next array with text that follows from colums. mom_ filled to new array will look like mmo_. Then I cout crypted text. I hope u understood whatI did there :D
here is code
//wal = kolumny=wiersze
#include <cstdlib>
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
void pole(int &a,const int &l);
void tab(const char &s[],char &d[], char &f[],const int a);
int main(){
string code;
cin >> code;
int wall=1;
int d=code.length();
char tekst[d];
pole(wall,d);
strcpy(tekst,code);
char kw[wall][wall];
char szyfr[d];
tab(tekst,kw,szyfr,wall);
for (int i=0;i<d;i++)
cout << szyfr[i] << endl;
system("PAUSE");
return 0;
}
void pole(int &a,const int &l){
if (a*a < l)
pole(a+=1,l);
}
void tab(const char &s[],char &d[], char &f[],const int a){
int i=0;
for (int x=0;x<a;x++,i++){
for (int y=0;y<a;y++,i++){
if(s[i])
d[x][y]=s[i];
else d[x][y]=='_';
f[i]=d[x][y];
}
}
}
d[x][y] has no meaning in tab d is a single dimension array. You will have to pass the first dimension as argument and use it when indexing. Something like:
void tab(const char &s[],char* &d, char &f[],const int a, int d_num_cols){
int i=0;
for (int x=0;x<a;x++,i++){
for (int y=0;y<a;y++,i++){
if(s[i])
d[x*d_num_cols + y]=s[i];
else d[x*d_num_cols + y]=='_';
f[i]=d[x*d_num_cols + y];
}
}
}

I get a number 2 when I reverse my string

I wrote this code to reverse strings. It works well, but when I enter short strings like "american beauty," it actually prints "ytuaeb nacirema2." This is my code. I would like to know what is wrong with my code that prints a random 2 at the end of the string. Thanks
// This program prompts the user to enter a string and displays it backwards.
#include <iostream>
#include <cstdlib>
using namespace std;
void printBackwards(char *strPtr); // Function prototype
int main() {
const int SIZE = 50;
char userString[SIZE];
char *strPtr;
cout << "Please enter a string (up to 49 characters)";
cin.getline(userString, SIZE);
printBackwards(userString);
}
//**************************************************************
// Definition of printBackwards. This function receives a *
// pointer to character and inverts the order of the characters*
// within it. *
//**************************************************************
void printBackwards(char *strPtr) {
const int SIZE = 50;
int length = 0;
char stringInverted[SIZE];
int count = 0;
char *strPtr1 = 0;
int stringSize;
int i = 0;
int sum = 0;
while (*strPtr != '\0') {
strPtr++; // Set the pointer at the end of the string.
sum++; // Add to sum.
}
strPtr--;
// Save the contents of strPtr on stringInverted on inverted order
while (count < sum) {
stringInverted[count] = *strPtr;
strPtr--;
count++;
}
// Add '\0' at the end of stringSize
stringInverted[count] == '\0';
cout << stringInverted << endl;
}
Thanks.
Your null termination is wrong. You're using == instead of =. You need to change:
stringInverted[count] == '\0';
into
stringInverted[count] = '\0';
// Add '\0' at the end of stringSize
stringInverted[count] == '\0';
Should use = here.
What is wrong with your code is that you do not even use strlen for counting the length of the string and you use fixed size strings (no malloc, or, gasp new[]), or the std::string (this is C++)! Even in plain C, not using strlen is always wrong because it is hand-optimized for the processor. What is worst, you have allocated the string to be returned (stringInverted) from the stack frame, which means when the function exits, the pointer is invalid and any time the code "works" is purely accidental.
To reverse a string on c++ you do this:
#include <iostream>
#include <string>
int main() {
std::string s = "asdfasdf";
std::string reversed (s.rbegin(), s.rend());
std::cout << reversed << std::endl;
}
To reverse a string in C99 you do this:
char *reverse(const char *string) {
int length = strlen(string);
char *rv = (char*)malloc(length + 1);
char *end = rv + length;
*end-- = 0;
for ( ; end >= rv; end --, string ++) {
*end = *string;
}
return rv;
}
and remember to free the returned pointer after use. All other answers so far are blatantly wrong :)

passing vector<char> to a pointer char*

how do I pass a char vector to a char*? I know this problem could easily be solved with a predefined char[] array with a SIZE const, but I want the flexibility of a vector because there will be no predefined size.
using namespace std;
//prototype
void getnumberofwords(char*);
int main() {
//declare the input vector
vector<char> input;
/*here I collect the input from user into the vector, but I am omitting the code here for sake of brevity...*/
getnumberofwords(input);
//here is where an ERROR shows up: there is no suitable conversion from std::vector to char*
return 0;
}
void getnumberofwords(char *str){
int numwords=0;
int lengthofstring = (int)str.size();
//this ERROR says the expression must have a case
//step through characters until null
for (int index=0; index < lengthofstring; index++){
if ( *(str+index) == '\0') {
numwords++;
}
}
}
You can use data() member to get the pointer to the underlying array:
getnumberofwords(input.data());
The most obvious is to pass &your_vector[0]. Be sure to add a NUL to the end of your vector first though.
Alternatively, use std::string instead of std::vector<char>, in which case you can get a NUL-terminated string with the c_str member function.
Edit: I have to wonder, however, why getnmberofwords would be written to accept a char * unless it's some old C code that you just can't get away from using.
Given a typical definition of "word" counting some words that start out in a string can be done something like this:
std::istringstream buffer(your_string);
size_t num_words = std::distance(std::istream_iterator<std::string>(buffer),
std::istream_iterator<std::string>());
You should pass the reference of the vector to the function getnumberofwords.
void getnumberofwords(vector<char>& str){
int numwords=0;
int lengthofstring = str.size();
for (int index=0; index < lengthofstring; index++){
if ( str[index] == '\0') {
numwords++;
}
}
}
There is no method for converting the type from vector to pointer.
here's what I ended up doing which worked:
#include <iostream>
#include <cstring>
#include <string>
#include <iomanip>
using namespace std;
//prototype
void getnumberofwords(char*);
void getavgnumofletters(char*, int);
int main() {
const int SIZE=50;
char str[SIZE];
cout<<"Enter a string:";
cin.getline(str, SIZE);
getnumberofwords(str);
return 0;
}
void getnumberofwords(char *str){
int numwords=0;
int lengthstring=strlen(str);
//step through characters until null
for (int index=0; index < lengthstring; index++){
if (str[index] ==' ') {
numwords++;
}else{
continue;
}
}
numwords+=1;
cout<<"There are "<<numwords<<" in that sentence "<<endl;
getavgnumofletters(str, numwords);
}
void getavgnumofletters(char *str, int numwords) {
int numofletters=0;
double avgnumofletters;
int lengthstring=strlen(str);
//step through characters until null
for (int index=0; index < lengthstring; index++){
if (str[index] != ' ') {
numofletters++;
}else{
continue;
}
}
avgnumofletters = (double)numofletters/numwords;
cout<<"The average number of letters per word is "<<setprecision(1)<<fixed<<avgnumofletters<<endl;
}
/*