Ошибка с strcpy и ее вторым аргументом

Когда я пытаюсь скомпилировать эту программу, я получаю ошибки (приведенные ниже кода) относительно второго аргумента strcpy. Я честно в тупике, что делать, чтобы это исправить. И мне жаль, если мой код неэффективен или некрасив; Я только начинающий студент CS.

#include "stdafx.h"
#include <iostream>
#include <ctime>
using namespace std;

int main(){   


 int r = 0;
 char *article[]={"the", "a", "one", "some", "any"};
 char *noun[]={"boy","girl","dog","town","car"};
 char *verb[]={"drove","jumped","ran","walked","skipped"};
    char *preposition[]={"to","from","over","under","on"};
    char sentence [80];

 srand(time(NULL));
 for(int i=0;i<=20;i++){

    r = (rand()%5);
 strcpy(sentence,*article[r]);
 strcat(sentence," ");
    r = (rand()%5);
 strcat(sentence,*noun[r]);
 strcat(sentence," ");
 r = (rand()%5);
 strcat(sentence,*verb[r]);
 strcat(sentence," ");
 r = (rand()%5);
 strcat(sentence,*preposition[r]);
 strcat(sentence," ");
 r = (rand()%5);
 strcat(sentence,*article[r]);
 strcat(sentence," ");
 r = (rand()%5);
 strcat(sentence,*noun[r]);
 strcat(sentence,".");
 }

 sentence[0]= toupper(sentence[0]);
 cout<<sentence <<endl;


 system("pause");
 return 0;}

1>Compiling...
1>assignment 8.cpp
1>e:\assignment 8\assignment 8\assignment 8.cpp(16) : warning C4244: 'argument' : conversion from 'time_t' to 'unsigned int', possible loss of data
1>e:\assignment 8\assignment 8\assignment 8.cpp(20) : error C2664: 'strcpy' : cannot convert parameter 2 from 'char' to 'const char *'
1>        Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
1>e:\assignment 8\assignment 8\assignment 8.cpp(23) : error C2664: 'strcat' : cannot convert parameter 2 from 'char' to 'const char *'
1>        Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
1>e:\assignment 8\assignment 8\assignment 8.cpp(26) : error C2664: 'strcat' : cannot convert parameter 2 from 'char' to 'const char *'
1>        Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
1>e:\assignment 8\assignment 8\assignment 8.cpp(29) : error C2664: 'strcat' : cannot convert parameter 2 from 'char' to 'const char *'
1>        Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
1>e:\assignment 8\assignment 8\assignment 8.cpp(32) : error C2664: 'strcat' : cannot convert parameter 2 from 'char' to 'const char *'
1>        Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
1>e:\assignment 8\assignment 8\assignment 8.cpp(35) : error C2664: 'strcat' : cannot convert parameter 2 from 'char' to 'const char *'
1>        Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast

person sk8bum    schedule 11.11.2010    source источник
comment
почему бы не использовать std::string?   -  person Sam Miller    schedule 11.11.2010
comment
Отмечено как домашнее задание. Если это не так, пожалуйста, не стесняйтесь удалить тег.   -  person John Dibling    schedule 11.11.2010
comment
К тому же это не домашнее задание. Это я пытаюсь сделать программу с тем, что я узнал в классе   -  person sk8bum    schedule 13.11.2010


Ответы (6)


ОПАСНОСТЬ. strcat() И strcpy() ЯВЛЯЮТСЯ ОСНОВНЫМИ ПРИЧИНАМИ РАКА КОДА. Их использование подвергает вас всевозможным переполнениям буфера. Используйте strncat()/strncpy() или (еще лучше) просто используйте std::string, поскольку вы используете C++!

strcat() и strcpy() ожидают, что их аргументы будут строками. *article[r] — это одна строка, chararticle[r] — это нужная вам строка. Итак, опускаем ведущие звездочки.

person Jonathan Grynspan    schedule 11.11.2010
comment
Спасибо за вашу помощь. Причина использования такого большого количества strcpy и strcat в том, что это то, о чем мы узнали, поэтому мне пришлось использовать это в этой программе. - person sk8bum; 11.11.2010
comment
Скажите своему профессору или учителю, что он учит колдовству. Злое злое программирование колдовства. Вы никогда не должны никогда использовать strcat() или strcpy() — даже под дулом пистолета! - person Jonathan Grynspan; 12.11.2010

У вас на одну звездочку слишком много — noun[r] уже дает вам char*, поэтому вам не нужно добавлять дополнительные * во второй параметр.

Кроме того, strcat является небезопасной функцией и может неожиданно привести к сбою вашей программы, если ваш буфер (в вашем случае sentence) слишком мал для содержимого.

Пожалуйста, используйте вместо этого strncat - вам нужно будет добавить еще один параметр к этой функции, а именно размер буфера - в данном случае 80. Тогда в случае недостаточного размера буфера вместо сбоя программы вы просто заметите, что ваше предложение обрезается в конце.

person Kos    schedule 11.11.2010

Ваши артикли, существительные и глаголы представляют собой массивы указателей на символы. При выборе элемента в массиве для использования вы получаете char* к слову для использования. Этого char* ожидает strcpy — когда вы разыменовываете char* (т. е. article[r]), вы получаете char, а не char.

Кроме того, strcpy является небезопасным строковым оператором, поэтому он может перезаписывать большие участки памяти или иным образом открывать зияющие дыры в безопасности. Есть ли причина, по которой вам не разрешено использовать std::string для этого назначения?

person agent oranje    schedule 11.11.2010

Слишком много разыменований, т.е. сдача:

strcpy(sentence,*article[r]);

to

strcpy(sentence, article[r]);

и аналогично для других случаев.

person Paul R    schedule 11.11.2010

*article[r] является значением типа char. Это первый символ строки. strcpy ожидает адрес строки, которая просто article[r].

person Matt K    schedule 11.11.2010

Вместо

 strcpy(sentence,*article[r]);

вы хотите

 strcpy(sentence,article[r]);
person Andrew Stein    schedule 11.11.2010