简体   繁体   中英

How to swap strings?

I am trying to swap strings. For one of my functions of my class, I am passing in two strings and I also created a temp variable. I have been trying to compile my code, but it says "no suitable function for conversion from std::string to const char* exists.

void CdLib::swap(string *s1, string *s2)
{
    string temp;

    strcpy(temp, *s1);
    strcpy(*s1, *s2);
    strcpy(*s1, temp);
}
class CdLib
{
public:

    int n;
    char Cd[N_MAX];

    string artist;
    string title;
    int year;
    string genre;
    string fan;
    string imageURL;

    CdLib();
    void setFromFile(string fileName);
    void print(string label);
    void sortByYear();
    void sortByArtist();
    void sortByTitle(string genres[]);

private:
    void swap(int *a, int *b);
    void swapStrings(string *s1, string *s2);
};

I'm confused why it is trying to convert between string and char when they should all be string. Thank you.

strcpy() takes char* pointers, not string* pointers. It you are not allocating any memory for strcpy() to copy into.

Rather than using strcpy() at all, a better solution is to use std::string::operator= instead:

void CdLib::swap(string *s1, string *s2)
{
    string temp = *s1;
    *s1 = *s2;
    *s1 = temp;
}

Or better, std::swap() :

void CdLib::swap(string *s1, string *s2)
{
    std::swap(*s1, *s2);
}

I am trying to swap strings

Why would you need to? Sorting can be accomplished via std::sort and you don't have to worry about how the strings get swapped - that's the beauty of C++, such basic operations are all implemented in the standard library.

  1. std::swap supports pretty much everything, so use that.

  2. Don't pass strings as arguments by value. Pass them by const reference. Return them by value. If a function is intended to modify a string in place, then it should take it by non-const reference (ie "just" a reference).

  3. Don't write using namespace std - it's bad practice.

I guess that the CdLib class is some sort of a CD library, but you haven't told us what else your program should do.

If I were to write a sketch of this, I'd start with a structure representing the CD information, comparison functions for the CD that can be used in sorting, a function to print out the CD information, and a way to stream the CD information to/from an ostream/istream:

#include <algorithm>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>

struct CDInfo
{
    std::string artist;
    std::string title;
    std::string genre;
    std::string fan;
    std::string imageUrl;
    int year;

    friend void swap(CDInfo& a, CDInfo& b)
    {
        // see https://stackoverflow.com/a/2684544/1329652 for rationale
        using std::swap; // bring in swap for built-in types

        swap(a.artist, b.artist);
        swap(a.title, b.title);
        swap(a.genre, b.genre);
        swap(a.fan, b.fan);
        swap(a.imageUrl, b.imageUrl);
        swap(a.year, b.year);
    }
};

bool lessByYear(const CDInfo &l, const CDInfo &r) {
    return l.year < r.year;
}

bool lessByArtist(const CDInfo &l, const CDInfo &r) {
    return l.artist < r.artist;
}

void print(std::ostream &os, const CDInfo &cd) {
    os <<   "Artist:   " << cd.artist
       << "\n  Title:  " << cd.title
       << "\n  Genre:  " << cd.genre
       << "\n  Fan:    " << cd.fan
       << "\n  Image:  " << cd.imageUrl
       << "\n  Year:   " << cd.year << "\n";
}

std::istream &operator>>(std::istream &is, CDInfo &cd)
{
    std::string year;
    std::getline(is, cd.artist);
    std::getline(is, cd.title);
    std::getline(is, cd.genre);
    std::getline(is, cd.fan);
    std::getline(is, cd.imageUrl);
    if (std::getline(is, year)) cd.year = std::stoi(year);
    return is;
}

std::ostream &operator<<(std::ostream &os, const CDInfo &cd)
{
    os << cd.artist << '\n' << cd.title << '\n'
       << cd.genre << '\n' << cd.fan << '\n'
       << cd.imageUrl << '\n' << cd.year << '\n';
    return os;
}

Then I'd write a class representing the CD library, with methods to access the individual CDs, iterators to access the entire collection, methods using the std::sort algorithm and the comparison functions to sort the library, and methods to load/save it from/to file, and to print the entire library (by default to stdout):

class CDLibrary
{
    std::vector<CDInfo> m_CDs;

public:
    CDLibrary() = default;

    int count() const { return m_CDs.size(); }
    void resize(int newCount) { m_CDs.resize(newCount); }

    CDInfo &getCD(int index) { return m_CDs[index]; }
    const CDInfo &getCD(int index) const { return m_CDs[index]; }

    auto begin() { return m_CDs.begin(); }
    auto end() { return m_CDs.end(); }
    auto begin() const { return m_CDs.begin(); }
    auto end() const { return m_CDs.end(); }
    auto cbegin() const { return m_CDs.begin(); }
    auto cend() const { return m_CDs.end(); }

    void sortByYear() {
        std::sort(begin(), end(), lessByYear);
    }

    void sortByArtist() {
        std::sort(begin(), end(), lessByArtist);
    }

    void addCD(const CDInfo &cd) {
        m_CDs.push_back(cd);
    }

    void removeCD(int index) {
        m_CDs.erase(m_CDs.begin() + index);
    }

    bool load(const std::string &filename);
    bool save(const std::string &filename) const;
    
    void printAll(std::ostream &os = std::cout) const {
        int n = 1;
        for (auto &cd : *this) {
            os << "--- CD #" << n << '\n';
            print(os, cd);
        }
    }
};

Of course I'd also implement the streaming operators for the entire library, just as we did for the individual CDInfo:

std::istream &operator>>(std::istream &is, CDLibrary &lib) {
    std::string count;
    if (std::getline(is, count)) {
        lib.resize(std::stoi(count));
        for (auto &cd : lib)
            if (!(is >> cd)) break;
    }
    return is;
}

std::ostream &operator<<(std::ostream &os, const CDLibrary &lib) {
    if (!(os << lib.count() << '\n')) return os;
    for (auto &cd : lib)
        if (!(os << cd)) break;
    return os;
}

Then, the load and save convenience methods can be expressed n terms of those streaming operators:

bool CDLibrary::load(const std::string &filename) {
    std::ifstream ifs(filename);
    try {
        return ifs.good() && ifs >> *this;
    } catch (...) {}
    return false;
}

bool CDLibrary::save(const std::string &filename) const {
    std::ofstream ofs(filename);
    return ofs.good() && ofs << *this;
}

Hopefully this gives you some idea how such code might look. I'm not quite sure what you expected to achieve with void sortByTitle(string genres[]) , so I didn't implement it. Feel free to comment under this answer to explain, as well as edit the question to make it clear what is the functionality you need.

#include <iostream>
#include<bits/stdc++.h>
using namespace std;

int main() {
    string str1 = "Hello";
    string str2 = "World";
    swap(str1,str2);
    cout<<str1<<" ";
    cout<<str2;
}

o/p: Success #stdin #stdout 0s 4492KB World Hello

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM