2013-07-12 4 views
-8
#include<iostream> 
using namespace std; 
int main() 
{ 
    char *name="Siva",*str; 
    for(int i=0;i<strlen(name);i++) 
    { 
     str[i]=name[i]; 
    } 
    cout<<str; 
    return 0; 
} 

Первая программа дает выход Sivaœ> т.е. шива с некоторыми значениями мусора .... Но второй программы показывают ошибки сегментации ... Пожалуйста, помогите мне найти точный ответ ...C++ символьные * проблемы

#include<iostream> 
using namespace std; 
int main() 
{ 
    int i=0; 
    char *name="Siva",*str; 
    for(i=0;i<strlen(name);i++) 
    { 
     str[i]=name[i]; 
    } 
    cout<<str; 
    return 0; 
} 
+0

Что вы пишете _to_? Что означает 'str' point _at_? – sehe

+0

Что бы вы хотели ответить ** тоже **? Вы только описали, как ведут себя ваши программы, а не то, что проблема, или то, что вы хотите, чтобы они делали или что вы ожидаете от них – jalf

+0

. Тогда как это дает ответ для первого случая ...... – user2390140

ответ

1

str[i]=name[i]; является незаконным, вызывает неопределенное поведение, потому что вы не выделили память для str.

Перед цикл выделения памяти для строки назначения str:

str = malloc (strlen(name) + 1); 

Также вы позабыв окончание строки, после того, как для цикла добавить строку прекратить str[i] = '\0';
Undefined behavior относится к компьютерному коду, поведение которого непредсказуемо.

Вы код должен быть:

char *name="Siva", *str; 
str = malloc (strlen(name) + 1); // mistake 
for(int i=0;i<strlen(name);i++) 
{ 
    str[i]=name[i]; 
} 
str[i] = '\0'; // forgetting 

Для дальнейшего понимания вы можете прочитать этот ответ: strcat() implementation works but causes a core dump at the end

+0

Тогда как это дает ответ для первого случая ...... – user2390140

+0

Это неопределенное поведение. Все может случиться. – tangrs

+2

«Неопределенный» означает «Это может сработать, а может и нет». –

3

Вы неопределенное поведение здесь:

str[i]=name[i]; 

str не инициализирован ни к чему , Вы пишете места, которые не должны.

2

Это потому, что у вас нет выделенной памяти для str. (Это приведет к неопределенному поведению)

Вы можете смешивать, что с помощью merory функции распределения, как в этом примере:

#include<iostream> 
using namespace std; 
int main() 
{ 
    char *name="Siva",*str; 
    // Allocate memory with malloc 
    str = (char*)malloc((strlen(name)+1) * sizeof(char)); 
    for(int i=0;i<strlen(name);i++) 
    { 
     str[i]=name[i]; 
    } 
    str[strlen(name)] = 0; 
    cout<<str; 
    // Free the allocated memory 
    free(str); 
    return 0; 
} 

Как вы используете C++, вы можете сделать:

#include<iostream> 
using namespace std; 
int main() 
{ 
    char *name="Siva",*str; 
    // Allocate memory with new 
    str = new char[strlen(name) + 1]; 
    for(int i=0;i<strlen(name);i++) 
    { 
     str[i]=name[i]; 
    } 
    str[strlen(name)] = 0; 
    cout<<str; 
    // Free the allocated memory 
    delete []str; 
    return 0; 
} 

EDIT: Причина, по которой у вас есть некоторые странные символы в конце вашего вывода, состоит в том, что, поскольку строка не заканчивается символом '\ 0', она будет продолжать печатать ее. (Это произойдет, только если у вас нет segmentation fault)

+0

Тогда как это дает ответ – user2390140

+1

Это неопределенное поведение. Иногда операционная система позволяет вашей программе получать доступ к этой памяти. Но чаще встречается «ошибка сегментации» ... –

+0

«Вы должны делать» - это должно быть странное значение слова «должно», о котором я ранее не знал. – sehe

3

Есть две проблемы с этим.

  1. Указатель str не указывает на выделенную память, поэтому запись через него является неопределенным поведением.
  2. Даже если это действительно указывает на действительную память, вы не записываете правильный объем данных. При копировании строки вам нужно скопировать байт 0 в конце, который отмечает конец строки; поэтому верхний предел вашей петли должен соответствовать strlen(name) + 1. Или вы можете использовать библиотечный метод, например strdup(), вместо своего собственного цикла for.

Причина, «рабочие» версия печатает некоторый мусор символы в том, что нет никакого 0 в конце скопированной строки сказать iostreams, чтобы остановить печать.Причина, по которой «рабочий» не срабатывает, а другая делает, - это просто безумная удача: мусор в str, случайно, указывает на память, на которую вы можете писать, в то время как в программе сбоя она указывает в память вы не разрешено писать. Просто как тот.

1

Есть пара проблем с вашим кодом.

Во-первых, * str не выделяется, поэтому он начинается с указания на любой бит памяти, с которого начинается значение указателя.

Во-вторых, strlen() возвращает длину строки, исключая завершающий нулевой символ. Итак, что вы делаете, это копирование всех значений имени в некоторый случайный бит памяти, а не завершение его, а затем сообщение системе распечатать это, что может быть любой длины.

5
char *name="Siva",*str; 
for(int i=0;i<strlen(name);i++) 
{ 
str[i]=name[i]; 
} 

str - указатель, но это еще не указывает на что-либо.

Поскольку вы в C++, вы должны использовать std::string:

#include<iostream> 
#include <string> 

using namespace std; 
int main() 
{ 
    char *name="Siva"; 
    std::string str; 
    for(int i=0;i<strlen(name);i++) 
    { 
    str += name[i]; 
    } 
    cout<<str; 
    return 0; 
} 

Еще лучше, чтобы избавиться от рукописного цикла:

#include <algorithm> 
int main() 
{ 
    char *name="Siva"; 
    std::string str; 
    std::copy (name, name + strlen (name), std::back_inserter (str)); 
    cout<<str; 
    return 0; 
} 

Лучше даже еще, нет никаких причин, в этом конкретном примере, почему вы должны сделать что-либо из этого:

char* name = "Silva"; 
std::string str = name; 
cout << str; 

Кстати, строковые литералы в C++ являются по своей сути const:

const char* name = "Silva"; 

Если вы действительно должны использовать char*, сначала я бы сильно вопрос, почему, и тогда я сказал бы вам, чтобы сделать это:

int main() 
{ 
    const char *name="Siva"; 
    char* str = new char [strlen (name)+1]; // +1 for the null terminator 
    strcpy (name, str); 
    cout << str; 
    delete [] str; 
    return 0; 
} 

Я бы еще сильнее вопрос вашу потребность, чтобы скопировать его байт за байтом:

int main() 
{ 
    const char *name="Siva"; 
    char* str = new char [strlen (name)+1]; // +1 for the null terminator 
    for (size_t i = 0; i < strlen (name); ++i) 
    str [i] = name [i]; 
    str [strlen (name)] = '\0'; 
    cout << str; 
    delete [] str; 
    return 0; 
} 
+0

Я должен предположить, что вы играете профессора педанта здесь: 'std :: copy (имя, имя + strlen (имя), std :: back_inserter (str))'. Приходите на – sehe

+1

@sehe: Да, просто пытаюсь показать несколько разных способов кожи кошки. –

0

Ваша проблема с использованием полукокса массивов и указателей для представления строк в языке, имеет правильный тип строки.

#include <iostream> 
#include <string> 
using namespace std; 

int main() 
{ 
    string name = "Siva", str; 
    str = name; 
    cout << str; 
    return 0; 
} 
0

Проблема с str[i]=name[i] вы должны знать, что C++ не заботится о memory leaks как Java или некоторые другие. Таким образом, вы должны выделить память переменной или указателю, чтобы избежать этих проблем. Уже есть несколько ответов, вы можете также попробовать

str=new char[strlen(name)+1]; 

и не забудьте завершить массив символов с нулем, когда вы сделали копию. В этом случае

str[strlen(name)]='\0'; 
+0

Вы упоминаете утечки памяти, но не упоминаете 'delete', который должен быть вызван, чтобы избежать утечек памяти./Кроме того, если вы используете Java, вы можете быть удивлены тем фактом, что C++ имеет строковый тип (' std :: string'), который управляет памятью (RAII). – milleniumbug

+0

Это не тот случай. Я знаю C++ больше, чем Java. Может быть, вы удивлены, когда я был студентом, я использовал Turbo C++, ни один класс String, а затем я полностью обработал всю строку. –

+0

Я знаю, и * Мне все равно * - Я проверил свой календарь и увидел, что теперь это год 2013. Тем не менее, я бы сказал, что вы не упоминаете, что 'delete []' должен использоваться после 'new []'. Также, как вы видите, C++ развивается ('std :: string' был добавлен в * 1998 *), а также его использование. – milleniumbug

Смежные вопросы