Разбор аргументов командной строки
От: mansur https://netmontools.com
Дата: 07.01.04 18:52
Оценка:
Помогите, плз, почему в первом случае памяти под строку выделено столько, сколько запрашивал, а в остальных случаях — нет?
Вместо new пробовал malloc, то же самое.
Компилил VC++ 6.0 SP4.

Код:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char** argv)  //Использую: example HTTP://mshome.manser.net/Ch13/Login.asp
{

    const int lenght = strlen(argv[1]);
    char* tmp = new char[lenght];  
    strcpy(tmp, argv[1]);
    printf("\n%d", lenght);  //39
    printf("\n%s", tmp);  //39 символов, как и должно быть.
    
    int j = 0, k = 0, l = 0, m =0, n = 0;

    for(j = 0; j < lenght; j++)
    {
        if(tmp[j] ==':')
        {
            k = j + 3;  
            break;
        }
    }

    char* proto = new char[j];  
    const int lproto = strlen(proto);
    printf("\n%d\n%d", j, lproto);  //j=4, lproto=17, почему?
    strncpy(proto, tmp,j);  
    printf("\n%s", proto);  //17 символов.

    n = k;  

    for(j = k; j < lenght; j++)
    {
        if(tmp[j] == '/')
        {
            l = j - n;  
            break;
        }
        continue;
    }    
    
    char* hst = new char[l];  
    const int lhst = strlen(hst);

    for(j = n ; j < (l + n); m++, j++)  
    {
          hst[m] = tmp[j];  
    }
    printf("\n%d\n%d", l, lhst);  //l=17, lhst=33, почуму?
    printf("\n%s", hst);  //33 символа.

    k = j;  

    for(j = k; j < lenght; j++)
    {
        tmp[j];  
    }
    l = j - k;

    char* dr = new char[l];  
    const int ldr = strlen(dr);

    m = 0;

    for(j = k; j < lenght; m++, j++)  
    {
        dr[m] = tmp[j];  
    }
    printf("\n%d\n%d", l, ldr);  //l=15, ldr=33, почему?
    printf("\n%s", dr);  //33 символа.

    return 1;
}
... << RSDN@Home 1.1.0 stable >>

Исправлено форматирование. -- ПК
Re: Разбор аргументов командной строки
От: MaximE Великобритания  
Дата: 07.01.04 20:23
Оценка:
On Wed, 07 Jan 2004 18:52:19 GMT, mansur <16299@news.rsdn.ru> wrote:

> Помогите, плз, почему в первом случае памяти под строку выделено столько, сколько запрашивал, а в остальных случаях — нет?

> Вместо new пробовал malloc, то же самое.
> Компилил VC++ 6.0 SP4.

> Код:
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
>
> int main(int argc, char** argv)  //Использую: example HTTP://mshome.manser.net/Ch13/Login.asp
> {
>
>     const int lenght = strlen(argv[1]);
>     char* tmp = new char[lenght];
//                         ^----потерял завершающий 0
// нужно new char[lenght + 1]

>     strcpy(tmp, argv[1]);
>     printf("\n%d", lenght);  //39
>     printf("\n%s", tmp);  //39 символов, как и должно быть.
>     
>     int j = 0, k = 0, l = 0, m =0, n = 0;
>
>     for(j = 0; j < lenght; j++)
>     {
>         if(tmp[j] ==':')
>         {
>             k = j + 3;
>             break;
>         }
>     }
>
>     char* proto = new char[j];
>     const int lproto = strlen(proto);
//                              ^---- бессмысленно: proto - неинициализированная память
>     printf("\n%d\n%d", j, lproto);  //j=4, lproto=17, почему?
>     strncpy(proto, tmp,j);
>     printf("\n%s", proto);  //17 символов.
//                   ^---- proto - строка из 4 символов без завершающего нуля

// ну и далее в таком духе


Пользуй std::string для строчек — не будет вышеперечисленных проблем. (но будут другие )

--
Maxim Egorushkin
MetaCommunications Engineering
http://www.meta-comm.com/engineering/
Posted via RSDN NNTP Server 1.8 beta
Re: Определить адрес функции CRT через GetProcAddress
От: fallen  
Дата: 07.01.04 20:37
Оценка:
Здравствуйте, mansur, Вы писали:

M> const int lenght = strlen(argv[1]);

M> char* tmp = new char[lenght];
M> strcpy(tmp, argv[1]);

надо выделять lenght+1 байт, забыл про терминирующий нуль

M> char* proto = new char[j];

M> const int lproto = strlen(proto);

а это что за хрень? выделил память, и смотришь длину чего? строки там нет

M> char* hst = new char[l];

M> const int lhst = strlen(hst);

см выше

M> char* dr = new char[l];

M> const int ldr = strlen(dr);

еще раз смотри выше

Сначала не мешало бы научится работать со строками и памятью!!!
Re: Разбор аргументов командной строки
От: mansur https://netmontools.com
Дата: 08.01.04 20:17
Оценка:
Исправил указанные ошибки, большое спасибо, но ничего не изменилось.
Кому не в тягость, скомпилите плз в 6-ой или 7-ой студии как пустой консольный проект,
и посмотрите вывод...
Код:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char** argv) //Использую: example HTTP://mshome.manser.net/Ch13/Login.asp
{

const int lenght = strlen(argv[1]);
char* tmp = new char[lenght +1]; //Исправил, ничего не изменилось.
strcpy(tmp, argv[1]);
printf("\n%d", lenght); //39
printf("\n%s", tmp); //39 символов, как и должно быть.

int j = 0, k = 0, l = 0, m =0, n = 0;

for(j = 0; j < lenght; j++)
{
if(tmp[j] ==':') //Количество символов протокола.
{
k = j + 3; //Пропускаем "://", до первого символа хоста.
break;
}
}

char* proto = new char[j]; //Буфер протокола
strncpy(proto, tmp,j);
const int lproto = strlen(proto);
printf("\n%d\n%d", j, lproto); //j=4, lproto=17, почему?
printf("\n%s", proto); //17 символов.

n = k; //Запоминаем начало хоста.

for(j = k; j < lenght; j++)
{
if(tmp[j] == '/')
{
l = j — n; //Количество символов хоста.
break;
}
continue;
}

char* hst = new char[l]; //Буфер хоста.

for(j = n ; j < (l + n); m++, j++)
{
hst[m] = tmp[j]; //Копируем хост.
}
const int lhst = strlen(hst);

printf("\n%d\n%d", l, lhst); //l=17, lhst=33, почуму?
printf("\n%s", hst); //33 символа.

k = j; //Запоминаем начало каталога.

for(j = k; j < lenght; j++)
{
tmp[j];
}
l = j — k; //Количество символов каталога.

char* dr = new char[l]; //Буфер каталога.
m = 0;

for(j = k; j < lenght; m++, j++)
{
dr[m] = tmp[j]; //Копируем каталог.
}
const int ldr = strlen(dr);

printf("\n%d\n%d", l, ldr); //l=15, ldr=33, почему?
printf("\n%s", dr); //33 символа.

return 1;
}
... << RSDN@Home 1.1.0 stable >>
Re: Разбор аргументов командной строки
От: Аноним  
Дата: 09.01.04 09:41
Оценка:
Здравствуйте, mansur, Вы писали:

M>Помогите, плз, почему в первом случае памяти под строку выделено столько, сколько запрашивал, а в остальных случаях — нет?

M>Вместо new пробовал malloc, то же самое.
M>Компилил VC++ 6.0 SP4.


По моему все дело в том что в первом случае строка копируется с символом конца строки
а в остальных случаях нет.

for(j = 0; j < lenght; j++)
{
if(tmp[j] ==':')
{
k = j + 3;
break;
}
}

//j — до конца не доехало
char* proto = new char[j];
strncpy(proto, tmp,j);//скопировались сиволы до ":" и конец строки не установлен а за ним кусок пустой памяти.
//если его установить
proto[j]=0;
//то все должно быть нормально
const int lproto = strlen(proto);
printf("\n%d\n%d", j, lproto); //j=4, lproto=17
printf("\n%s", proto); //17
Re[2]: Разбор аргументов командной строки
От: _Jane_ Украина  
Дата: 09.01.04 10:37
Оценка:
Здравствуйте, mansur, Вы писали:

M>Исправил указанные ошибки, большое спасибо, но ничего не изменилось.

M>Кому не в тягость, скомпилите плз в 6-ой или 7-ой студии как пустой консольный проект,
M>и посмотрите вывод...
M>Код:
M>#include <stdio.h>
M>#include <stdlib.h>
M>#include <string.h>

M>int main(int argc, char** argv) //Использую: example HTTP://mshome.manser.net/Ch13/Login.asp

M>{

M> const int lenght = strlen(argv[1]);

M> char* tmp = new char[lenght +1]; //Исправил, ничего не изменилось.

Зато теперь программа не будет падать или неправильно работать время от времени из-за того что пишет за пределы выделенной памяти.
strcpy всегда дописывает 0 символ в конце строки. strlen не считает этот ноль но он должен присутствовать как признак конца строки.

M> strcpy(tmp, argv[1]);

M> printf("\n%d", lenght); //39
M> printf("\n%s", tmp); //39 символов, как и должно быть.

M> int j = 0, k = 0, l = 0, m =0, n = 0;


M> for(j = 0; j < lenght; j++)

M> {
M> if(tmp[j] ==':') //Количество символов протокола.
M> {
M> k = j + 3; //Пропускаем "://", до первого символа хоста.

хм, а правильность ввода (что после двоеточия всегда 2 слеша) не проверяется? ну ладно
да и, кто сказал что ':' не может быть последним символом? Ну вот, опять вылазим за пределы строки

M> break;

M> }
M> }

M> char* proto = new char[j+1]; //Буфер протокола

M> strncpy(proto, tmp,j);
proto[j] = 0;
M> const int lproto = strlen(proto);
M> printf("\n%d\n%d", j, lproto); //j=4, lproto=17, почему?

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

M> printf("\n%s", proto); //17 символов.


M> n = k; //Запоминаем начало хоста.


M> for(j = k; j < lenght; j++)

M> {
M> if(tmp[j] == '/')
M> {
M> l = j — n; //Количество символов хоста.
M> break;
M> }
M> continue;
M> }

M> char* hst = new char[l+1]; //Буфер хоста.


M> for(j = n ; j < (l + n); m++, j++)

M> {
M> hst[m] = tmp[j]; //Копируем хост.
M> }
M> const int lhst = strlen(hst);

M> printf("\n%d\n%d", l, lhst); //l=17, lhst=33, почуму?

M> printf("\n%s", hst); //33 символа.

M> k = j; //Запоминаем начало каталога.


M> for(j = k; j < lenght; j++)

M> {
M> tmp[j];
M> }
M> l = j — k; //Количество символов каталога.

M> char* dr = new char[l]; //Буфер каталога.

M> m = 0;

M> for(j = k; j < lenght; m++, j++)

M> {
M> dr[m] = tmp[j]; //Копируем каталог.
M> }
M> const int ldr = strlen(dr);

M> printf("\n%d\n%d", l, ldr); //l=15, ldr=33, почему?

M> printf("\n%s", dr); //33 символа.

а где delete[] все те что выделены new[]?!!! меморилики

M> return 1;

M>}

Диагноз: учиться работать со строками и памятью, и/или использовать std::string, CString & so on
А также нормально именовать переменные (от всех этих tmp, j, k, n, m голова кругом идет, ну почему бы им не называться nCharsProtocol, nCatalogIndex, nHostIndex к примеру.
И не мешало бы проверить argc перед доступом к argv, хотя если програмулина запускается автоматически с параметрами это не так важно но все же.
Jane
Re[3]: Разбор аргументов командной строки
От: mansur https://netmontools.com
Дата: 12.01.04 03:56
Оценка:
Здравствуйте, _Jane_, Вы писали:

_J_>Здравствуйте, mansur, Вы писали:


M>> const int lenght = strlen(argv[1]);

M>> char* tmp = new char[lenght +1]; //Исправил, ничего не изменилось.

_J_>Зато теперь программа не будет падать или неправильно работать время от времени из-за того что пишет за пределы выделенной памяти.

_J_>strcpy всегда дописывает 0 символ в конце строки. strlen не считает этот ноль но он должен присутствовать как признак конца строки.

M>> for(j = 0; j < lenght; j++)

M>> {
M>> if(tmp[j] ==':') //Количество символов протокола.
M>> {
M>> k = j + 3; //Пропускаем "://", до первого символа хоста.

_J_>хм, а правильность ввода (что после двоеточия всегда 2 слеша) не проверяется? ну ладно

_J_>да и, кто сказал что ':' не может быть последним символом? Ну вот, опять вылазим за пределы строки

M>> break;

M>> }
M>> }

M>> char* proto = new char[j+1]; //Буфер протокола

M>> strncpy(proto, tmp,j);
_J_> proto[j] = 0;
M>> const int lproto = strlen(proto);
M>> printf("\n%d\n%d", j, lproto); //j=4, lproto=17, почему?

_J_>потому что нуль символа не было в конце строки. В первом случае где 39, повезло попасть на кусок памяти с нулем, в этом случае не повезло


_J_>а где delete[] все те что выделены new[]?!!! меморилики


_J_>Диагноз: учиться работать со строками и памятью, и/или использовать std::string, CString & so on

_J_>А также нормально именовать переменные (от всех этих tmp, j, k, n, m голова кругом идет, ну почему бы им не называться nCharsProtocol, nCatalogIndex, nHostIndex к примеру.
_J_>И не мешало бы проверить argc перед доступом к argv, хотя если програмулина запускается автоматически с параметрами это не так важно но все же.
Спасибо большое всем ответившим, всё исправил и заработало!
С уважением, Мансур М.Валиев.
... << RSDN@Home 1.1.0 stable >>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.