有没有更好的方法来为C++写这个?

Is there a better way to write this for C++?

本文关键字:C++ 更好 方法 有没有      更新时间:2023-10-16

目标是通过提取用空格分隔的单词,从输入的字符串创建子字符串。

子字符串本身必须是变量。

听起来很容易,但困难的是你只能使用 strcpy、strcmp、strlen、strcat、strncpy、strncmp、strnlen 和 strncat。

例:

输入:

"John 40 Hitman"

司机:

...
cout << word1 << endl 
     << word2 << endl 
     << word3 << endl;

输出:

John
40
Hitman

这是我的代码

#include <iostream>
#include <cstring>
#include <stdio.h>
int main(){
const char *string = "Name Age Job";
char name[10];
char age[10];
char job[10];
int length = strlen(string);
int temp = 0;
bool flag = false;
for(int i = 0; i < length + 1; i++){
  if(isspace(string[i]) && !flag){
    strncpy(name, string, i);
    name[i] = '';
    temp = i;
    flag = !flag;
    cout << name << endl;
    continue;
  }
  if(isspace(string[i])){
    strncpy(age, string + temp + 1, length - i - 1);
    age[temp - i] = '';
    temp = i;
    cout << age << endl;
    continue;
  }
  if(string[i] == ''){
    strncpy(job, string + temp + 1, length);
    job[temp - i] = '';
    cout << job << endl;
  }
}

它可以工作,但它必须使用标志布尔值,字符串不是动态的,仅适用于具有 2 个空格的字符串,并且有很多重复的代码。总的来说真的很卡顿,但我花了大约两个小时,我不知道如何改进它。

如果你想知道,这确实是一个家庭作业问题,但这是一个入门课,我的教授只想要只有 3 个单词的硬编码字符串的正确输出。但是,我想学习如何改进它,并且非常感谢任何帮助。谢谢。

您需要做的就是将空格' '替换为''(字符串末尾(,从而从原始字符串创建 3 个子字符串。下面的程序这样做,只是将字符串转储到cout但您也可以将指针保存在数组中(例如。 char* substring[3] (。

int main(){
    char string[] = "Name Age Job";
    char* temp = string;
    for(char* it = string; *it; ++it ) {
        if (*it == ' ') {
            *it = '';
            std::cout << temp << std::endl;
            temp= it + 1;
        }
    }
    std::cout << temp << std::endl;
}
仅使用

C 函数执行此操作的正确方法是使用 strtok ,尽管它会就地切碎一个字符串。

关于你的代码,有很多不必要的分支和检查。你应该避免continue,这是一个几乎 100% 确定的循环需要改进的迹象。每当您发现自己需要它时,通常都有更好的方法。

您还应该避免strncpy因为正如您所注意到的,跟踪何时终止 null 以及何时不终止是一种痛苦。这是一个危险的函数,比memcpy慢得多,可以在这里使用。

这是一个基于使用 2 个指针的简化版本,一个始终设置为指向下一个空格,另一个始终设置为指向下一个有效单词的开头。

#include <string.h>
#include <ctype.h>
#include <stdio.h>
const char* find_next_space (const char* str)
{
  while(*str != '' && !isspace(*str))
    str++;
  return str;
}
int main (void)
{
  const char str[] = "hello world how are you";
  char substr[5][10];

  const char* word_start = str;
  for(size_t i = 0; i<5; i++)
  {
    if(*word_start == '')
      break;
    const char* next_space = find_next_space(word_start); 
    size_t length = (size_t)(next_space-word_start);
    memcpy(substr[i], word_start, length); 
    substr[i][length] = '';
    puts(substr[i]);
    word_start = next_space+1;
  }
}

此代码通过不检查字符串是否合适并且不分配内存来简化事情。真正的生产质量 C 代码不会使用char [5][10]而是使用指针数组char* [5]其中每个指针都设置为指向动态分配的内存。

我同意@acraig5075,因为你的代码比C++更C。 如果您正在考虑使用 STL 字符串以C++编写此内容,则一种方法如下。

#include <iostream>
#include <string>
#include <sstream>
#include <vector>

std::vector<std::string> split_string( const std::string &srcString, const char &delimiterKeywrd )
{
    /**
     *  Splits a string according to a keyword delimiter and returns a vector with the 
     *  segments of the split string.
     *  
     *  Args:
     *      @param  srcString:          The required string to split.
     *      @param  delimiterKeywrd:    The delimiter keyword that the string will be splitted to
     *      @return segmentsVectr:      A vector holding the segments of the srcString that was splitted. 
     *
    */
    std::stringstream inputStr;
    inputStr.str( srcString );
    std::string segment;
    std::vector<std::string> segmentsVectr;
    while( std::getline( inputStr, segment, delimiterKeywrd ) )
    {
        segmentsVectr.push_back( segment );
    }
    return segmentsVectr;
}

int main() {
    std::string inputStr{"John 40 Hitman"};
    std::vector<std::string> result;
    char delimiterKeywrd = ' '; 
    result = split_string( inputStr, delimiterKeywrd );
    //  Iterate through the vector and print items on a different line.
    for ( const std::string &item : result )
    {
        std::cout << item << std::endl;
    }
    return 0;
}

检查 std::string 在 cpp首选项和示例,如果你不熟悉。 同样在这里,我正在使用std::stringstream,这使得使用std::getline变得容易。

如果 std::stringstream 不是您的首选方式,您可以随时从另一个关于按字符拆分字符串的问题中检查此实现。

希望这有帮助。