Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.75/8: Рейтинг темы: голосов - 8, средняя оценка - 4.75
0 / 0 / 0
Регистрация: 27.07.2009
Сообщений: 13
1

Вопрос о строках.

12.08.2009, 19:14. Просмотров 1608. Ответов 20
Метки нет (Все метки)

Здравствуйте, все.

Талдычу строки.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <stdio.h>
using namespace std;
 
int main() {
 
    char * pstr1="tes"; 
    short offset=strlen(pstr1)+1;
    
    pstr1="wxyz";
    for(offset*=-1;offset<(short)strlen(pstr1);offset++){
        cout<<"pstr1["<<offset<<"]=="<<*(pstr1+offset)<<endl;
    }
    return 0;
}
вывод
pstr1[-4]==t
pstr1[-3]==e
pstr1[-2]==s
pstr1[-1]==
pstr1[0]==w
pstr1[1]==x
pstr1[2]==y
pstr1[3]==z

Получается, что если присвоить указателю на символ новую строку, то выделятется новый кусок памяти(см. вывод).
Вопрос 1.
Нужно ли заботиться о уплывших байтах? Что-то подсказыватет, что надо.
Вопрос 2.
Если нужно, то подскажите как правильно все сделать.

Спасибо заранее читающим || отвечающим.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
12.08.2009, 19:14
Ответы с готовыми решениями:

проясните вопрос в строках
вот программа с объявлениями строк как тип стринг и как массив #include &quot;stdafx.h&quot; #include...

Найти наибольшие элементы в чётных строках матрицы, а наименьшие в нечётных строках
Дана матрица n*m. Найти наибольшие элементы в чётных строках, а наименьшие в нечётных строках. ...

Заменить отрицательные элементы в нечетных строках матрицы на нули, а в четных строках - на единицу
Заменить отрицательные элементы в нечетных строках матрицы на нули, а в четных строках - на единицу...

Во сколько раз сумма элементов, стоящих на четных строках, больше, чем на нечетных строках?
Задана целочисленная матрица. Во сколько раз сумма элементов, стоящих на четных строках, больше,...

20
инженер-системотехник
111 / 111 / 5
Регистрация: 10.03.2009
Сообщений: 533
12.08.2009, 19:33 2
Что ты понимаешь под уплывающими байтами? Вообще данные строки Являются статическими, т.е. размещаются на этапе компиляции и освобождать память из-под них не нужно. В то же время не факт, что вторую строку он разместит сразу за первой. Так что твои результаты - частный случай...
0
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
12.08.2009, 19:52 3
Получается, что если присвоить указателю на символ новую строку, то выделятется новый кусок памяти(см. вывод).
Выделяется память из стека,предназначенная для локальных переменных,и все локальные объекты уничтожаются по выходе из блока.(Я полагаю,вызывается деструктор.)
Вопрос 1.
Нужно ли заботиться о уплывших байтах? Что-то подсказыватет, что надо.
Вопрос 2.
Если нужно, то подскажите как правильно все сделать.
В данном случае не нужно.
Но если был использован оператор new,то тогда память нужно освобождать с помощью delete.
C++
1
2
3
4
   char *str = new char;
  ...
   delete [] str;// или
   delete str;
Потому что память выделяется "динамически".То есть программист сам выделяет её из общего доступного пространства и сам должен её освобождать.Я пока сам смутно понимаю данную тему,но вроде так.
0
depict1
281 / 146 / 4
Регистрация: 11.07.2009
Сообщений: 606
12.08.2009, 20:02 4
Цитата Сообщение от #pragma Посмотреть сообщение
* *char *str = new char;
* ...
* *delete [] str;// или
* *delete str;
что значит "// или"? в данном случае мы выделяем память используя operator new не для массива, а для одиночного объекта. так что первая форма записи
C++
1
delete [] str
ошибочна
1
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
12.08.2009, 20:04 5
А если так?
C++
1
char *str = new char [1]
То есть один элемент не может быть массивом?И потом,при записи
C++
1
char *str=new char;
Выделяется же память под один байт,а если записать туда больше байт?Это ведь тоже будет массив?
0
576 / 570 / 65
Регистрация: 29.01.2009
Сообщений: 1,274
12.08.2009, 20:11 6
#pragma, если записать туда больше одного байта, то можно нарваться на ячейку памяти кем-то уже занятую.
1
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
12.08.2009, 20:14 7
Но всё таки запись
C++
1
delete []str
корректна,я проверил с компиляцией "gcc -ansi -pedantic -Wall"
0
MCSD: APP BUILDER
8787 / 1065 / 104
Регистрация: 17.06.2006
Сообщений: 12,604
12.08.2009, 20:46 8
#pragma,

char *str = new char [1]
То есть один элемент не может быть массивом?И потом,при записи
Это связано с особенностью адресной арифметики с C/C++
Указатель - он всегда указывает на ОДИН элемент (а этот элемент может быть например, массивом). при добавлении числа, машинный адрес изменяется на число * (размер области данных), так что если эта память принадлежит процессу, то мы можем юзать её. так достигается иллюзия работы как с массивом.
1
Эксперт С++
2919 / 1268 / 114
Регистрация: 27.05.2008
Сообщений: 3,465
12.08.2009, 22:48 9
Цитата Сообщение от #pragma Посмотреть сообщение
Но всё таки запись [...] корректна,я проверил с компиляцией "gcc -ansi -pedantic -Wall"
Это допустимо с точки зрения компилятора, однако, в соответствии с точным смыслом Стандарта (5.3.5/2), приводит к undefined behavior - неопределенному поведению программы. Если тебе повезет - программа будет работать, как будто ничего не произошло. Если не повезет.... значит, не повезет. В самом неудачном случае невезения будет время от времени появляться невоспроизводимый глюк в программе. И, по закону подлости, он обязательно проявится именно при демонстрации программы Самому Главному Боссу....
1
554 / 508 / 25
Регистрация: 23.07.2009
Сообщений: 2,359
Записей в блоге: 1
13.08.2009, 00:21 10
Цитата Сообщение от #pragma Посмотреть сообщение
Выделяется память из стека,предназначенная для локальных переменных,и все локальные объекты уничтожаются по выходе из блока.
в данном случае - нет. и прав Haster: строки находятся в поле констант.

хотите убедиться - посмотрите сюда:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
void func(){
    DWORD_PTR stackPtr;
    __asm mov [stackPtr], esp;
    cout<<"stack pointer in func: "<<stackPtr<<endl;
    char *pstr1="testestestestestestestestestestestestestestesAAA";
    cout<<"pstr1 in func: "<<pstr1<<endl;
}
 
void func2(){
    DWORD_PTR stackPtr;
    __asm mov [stackPtr], esp;
    cout<<"stack pointer in func2: "<<stackPtr<<endl;
    char *pstr1="111111111111111111111111111111111111111111111111111111222";
    cout<<"pstr1 in func2: "<<pstr1<<endl;
}
 
 
int main(...) {
    DWORD_PTR stackPtr;
    __asm mov [stackPtr], esp;
    cout<<"stack pointer in main before func() call: "<<stackPtr<<endl;
    func();
    __asm mov [stackPtr], esp;
    cout<<"stack pointer in main before func2() call: "<<stackPtr<<endl;
    func2();
    __asm mov [stackPtr], esp;
    cout<<"stack pointer in main after func2() call: "<<stackPtr<<endl;
}
выполните и посмотрите (советую в дибаггере посмотреть что расположено по данным адресам) куда указывает указатель стэка, и где находятся эти строчки. все поймете.

Добавлено через 33 минуты 56 секунд
дополню: указатели
C++
1
char *pstr1
, конечно, будут находиться именно в стэке
0
Эксперт С++
2919 / 1268 / 114
Регистрация: 27.05.2008
Сообщений: 3,465
13.08.2009, 10:21 11
Кстати, коллеги, вот простой тест, показывающий разницу между delete и delete[] формами:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>
using namespace std;
 
class test
{
public:
    test() { cout << "test ctor" << endl; }
    ~test() { cout << "test dtor" << endl; }
};
 
int main()
{
    test* p = new test[5];
    cout << "----------" << endl;
    delete p;
    //delete[] p;
 
    return 0;
}
 
/*
output:
test ctor
test ctor
test ctor
test ctor
test ctor
----------
test dtor
 
*/
Поскольку это частая ошибка начинающих программистов, мне представляется полезным проиллюстрировать ее.
0
554 / 508 / 25
Регистрация: 23.07.2009
Сообщений: 2,359
Записей в блоге: 1
13.08.2009, 12:06 12
теперь проверьте, правильно ли сработают

C++
1
2
    test** p = new test[5][10];
    delete[][] p;
,
C++
1
2
    test*** p = new test[5][10][20];
    delete[][][] p;
...

зачем такие заморочки писать, даже если это "правильно работает"?
0
Maniac
Эксперт С++
1446 / 948 / 158
Регистрация: 02.01.2009
Сообщений: 2,813
Записей в блоге: 1
13.08.2009, 12:11 13
Цитата Сообщение от novi4ok Посмотреть сообщение
теперь проверьте, правильно ли сработают

C++
1
2
    test** p = new test[5][10];
    delete[][] p;
,
C++
1
2
    test*** p = new test[5][10][20];
    delete[][][] p;
Даже не скомпелится..
0
0 / 0 / 0
Регистрация: 27.07.2009
Сообщений: 13
13.08.2009, 15:41  [ТС] 14
Спасибо за ответы всем. :-) Прочитал и понял как много нужно узнать :-).

Поставлю вопрос, касающийся моего листинга, так:
Переменная pstr1 будет размещена в стеке. Симолы "tes" и "wxyz" будут размещены в стеке или в динамической памяти или еще где-то?

Еще вопрос:
Что за стек пресловутый такой? Читал - про гору тарелок. получается, если в функции main() объявить три переменных(положить 3 тарелки друг на друга), то как мне достать нижнюю переменную? Куда положить две снятые тарелки?

Спасибо за ответы.
0
554 / 508 / 25
Регистрация: 23.07.2009
Сообщений: 2,359
Записей в блоге: 1
13.08.2009, 17:00 15
Цитата Сообщение от sledge Посмотреть сообщение
Переменная pstr1 будет размещена в стеке.
правильно.
Цитата Сообщение от sledge Посмотреть сообщение
Симолы "tes" и "wxyz" будут размещены в стеке или в динамической памяти или еще где-то?
"еще где-то". в области констатн. проще выражаясь, они будут являться частью тела вашего скомпилированного модуля.

Цитата Сообщение от sledge Посмотреть сообщение
Еще вопрос:
Что за стек пресловутый такой? Читал - про гору тарелок. получается, если в функции main() объявить три переменных(положить 3 тарелки друг на друга), то как мне достать нижнюю переменную? Куда положить две снятые тарелки?
вам не нужно об этом заботиться вообще, если вы пишете на с++, а не на ассемблере. вы обращаетесь к тарелкам по их именам, а не работаете с указателем стека непосредственно. эти детали берет на себя компилятор.
1
0 / 0 / 0
Регистрация: 27.07.2009
Сообщений: 13
13.08.2009, 20:42  [ТС] 16
Цитата Сообщение от novi4ok Посмотреть сообщение
правильно.

"еще где-то". в области констатн. проще выражаясь, они будут являться частью тела вашего скомпилированного модуля.
Похоже что так и есть.
C++
1
2
char * pstr1="tes";
for(int i=0;i<2;i++) *(pstr1+i)=char(i+65); pstr1[2]='\0';
Вылетает с ошибкой.

Прочитал - есть 5 областей. Мож кому интересно будет.
1. область глоб.перем. - хранятся глобальные переменные.
2. динамическая - создается/уничтожается new/delete.
3. регистровая память (хранятся вершина пресловутого стека,адрес команды...)
4. сегменты программы - программный код.
5. стековая память(Пресловутая )

Если пойти методом от противного то получается, что если объявить
C++
1
char * pstr1="tes";
то pstr1 попадет в стековую память, а сама строка "tes" в сегменты программы.
Поправьте.

Спасибо всем.
0
Эксперт С++
7171 / 3229 / 77
Регистрация: 17.06.2009
Сообщений: 14,166
13.08.2009, 20:55 17
Не в сегмент программы, а в read-only область данных программы (где хранятся все константы, строки).
1
Эксперт С++
2919 / 1268 / 114
Регистрация: 27.05.2008
Сообщений: 3,465
13.08.2009, 22:19 18
Если говорить о Win32-программе, в ней все инициализированные константы, и, в частности, строковые литералы (а упомянутый "tes" - это именно строковый литерал, а не строка!) размещаются в специальной секции PE-модуля с именем .rdata - read-only data. Хотя, зависит от компилятора, - компилятор от Борланда любит размещать такие константы прямо в секции .code - которая, разумеется, тоже read-only
Устройство эльф-модуля из никсов я подробно не копал, но, думаю, будет то же самое.
1
0 / 0 / 0
Регистрация: 27.07.2009
Сообщений: 13
13.08.2009, 22:29  [ТС] 19
Цитата Сообщение от odip Посмотреть сообщение
Не в сегмент программы, а в read-only область данных программы (где хранятся все константы, строки).
odip,CheshireCat , если Вас не затруднит - киньте ссылкой или скажите где почитать про эти чуднЫе области памяти, Потому как в той книге, что я читаю, - я нашел упоминание только о тех областях, которые я запостил в предыдущем сообщении.

Спасибо заранее.
0
Эксперт С++
2919 / 1268 / 114
Регистрация: 27.05.2008
Сообщений: 3,465
13.08.2009, 23:18 20
Например, вот: http://www.rsdn.ru/article/baseserv/pe_coff.xml
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
13.08.2009, 23:18

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

Вводится десять 99-значных чисел(в нечётных строках) и набор операций(+,-,*) между ними в (чётных строках). res/18?
Добрейшего времени суток, необходима помощь в решении задачи на с++. Сама задача: &quot;Вводится...

Дан целый массив максимальной размерности 20*20. Провести сортировку по возрастанию в нечетных строках массива и по убыванию в четных строках.
Дан целый массив максимальной размерности 20*20. Провести сортировку по возрастанию в нечетных...

Задана целочисленная матрица. Во сколько раз сумма элементов, стоящих на четных строках, больше, чем на нечетных строках.
Помогите с решением такой вот задачки: Задана целочисленная матрица. Во сколько раз сумма...

Определить, что больше сумма элементов в четных строках или произведение элементов в нечетных строках матрицы
Ребята, помогите пожалуйста кто может, код программы нужен. Заранее огромное спасибо Дан...

Как найти слова, которые повторяются в обеих строках, если разделяю слова в строках , используя Tokenizer
Нужно вывести слова, которые повторяются в обеих строках. Сказали, что нужно разделить строки на...

Элементы массива упорядочены по возрастанию элементов в строках. Переупорядочить массив по убыванию его элементов в строках
Элементы массива упорядочены по возрастанию элементов в строках. Переупорядочить массив по убыванию...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2020, vBulletin Solutions, Inc.