алгоритм выделения параметров из командной строки
Задача состоит в следующем:
Командная строка будет содержать только следующие символы: ∙ латинские буквы (большие и маленькие) и цифры, ∙ пробел (ASCII 32), ∙ двойные кавычки (ASCII 34).
Параметры записываются в командную строку подряд в порядке следования. Между каждыми двумя соседними параметрами вставляется один или несколько пробелов, чтобы отделить их друг от друга. Параметр может быть целиком заключён в двойные кавычки. Если внутри параметра есть пробелы, он заключён в двойные кавычки обязательно. Символов двойных кавычек в самих параметрах нет — ими лишь можно окружать параметры. Все параметры непустые.
Командная строка, которую необходимо разобрать, записана в единственной строке входного файла. Её длина не превышает 100 символов. Учтите, что в этой командной строке отсутствует имя исполняемого файла. В выходной файл нужно вывести искомые параметры командной строки, по одному параметру в строке. Каждый параметр должен быть заключён в квадратные скобки. Особый нулевой параметр (саму командную строку) выводить не нужно.
далее мой код. Он вроде как нормально работает, но при вводе более одного пробела на выходе какая-то непонятная каша, и я не могу понять в чем причина:
#include <stdio.h>
#include <conio.h>
#include <string.h>
int main()
{
char c;
do
{
scanf("%c", &c);
switch (c) {
case '"':
printf("[");
scanf("%c", &c);
while (c != '"')
{
printf("%c", c);
scanf("%c", &c);
}
//printf("]\n");
case ' ':
if (c != '\n')
{
scanf("%c", &c);
}
default:
while (c != ' ' && c != '\n')
{
printf("[%c", c);
scanf("%c", &c);
}
printf("]\n");
getch();
}
} while ( c!= '\n');
return 0;
}
Ответы (3 шт):
Я бы немного переписал ваше решение как то так (код на C#)
public List<string> GetParameters(string input)
{
var result = new List<string>();
int ind = 0;
while(ind < input.Length)
{
while(ind < input.Length && input[ind] == ' ') ind++;
if (ind == input.Length) break;
int start = ind;
ind++;
if (input[start] == '"')
{
while(ind < input.Length && input[ind] != '"') ind++;
result.Add(input.Substring(start + 1, ind - start-1));
}
else
{
while(ind < input.Length && input[ind] != ' ') ind++;
result.Add(input.Substring(start, ind - start));
}
ind++;
}
return result;
}
Проверка
GetParameters("\"abc d\" e").Dump();
GetParameters("\"long p \" \"p 2\" \"sht\" s pars").Dump();
Результат
Насчет "каши" не понял, но пару ошибок в алгоритме нашел:
Под конец каждого
caseнужно писатьbreakКомментарий
//printf("]\n");раскомментируйте, полезная строчка)case ' 'не понял почему он такой у вас, можно просто пропустить пробел написавbreak.В
defaultперед циклом печатать[а внутри цикла символы, а не каждую итерацию[%c.getch()тоже не понял зачем он тут.
Полный измененный код:
#include <stdio.h>
#include <conio.h>
#include <string.h>
int main()
{
char c;
do {
scanf("%c", &c);
switch (c) {
case '"':
printf("[");
scanf("%c", &c);
while (c != '"') {
printf("%c", c);
scanf("%c", &c);
}
printf("]\n");
break;
case ' ':
break;
default:
printf("[");
while (c != ' ' && c != '\n') {
printf("%c", c);
scanf("%c", &c);
}
printf("]\n");
}
} while (c != '\n');
return 0;
}
Результат программы:
У вас в задании написано: "Командная строка будет содержать только следующие символы: ∙ латинские буквы (большие и маленькие) и цифры, ∙ пробел (ASCII 32), ∙ двойные кавычки (ASCII 34)". Также запрещены кавычки внутри параметров и пустые параметры. Эти ограничения нужно учесть.
В общем, вот вариант, на мой взгляд гораздо более корректный (хоть может и не идеальный), т.к. осуществляет разбор с учётом возможных ошибок синтаксиса входной строки:
#include <stdio.h>
#include <conio.h>
#include <string.h>
#define MAX_LEN 1023
void InitCharMap();
enum STATE:char
{
STATE_SEARCH_PARAM,
STATE_IN_PARAM,
STATE_IN_QUOT_PARAM,
STATE_OUT_QUOT_PARAM,
STATE_BREAK
};
enum CHAR_TYPE:char
{
CHAR_FORBIDDEN = 0,
CHAR_EOL,
CHAR_SPACE,
CHAR_QMARK,
CHAR_SYMBOL
};
char g_CharMap[256] = {0};
int main()
{
char szInput[MAX_LEN+1];
STATE state = STATE_SEARCH_PARAM;
InitCharMap();
fputs("Enter the input string:> ",stdout);
fgets(szInput,MAX_LEN+1,stdin);
char* p = szInput;
while (state!=STATE_BREAK)
{
char c = *(p++);
char ct = g_CharMap[c];
if (ct==CHAR_FORBIDDEN)
{
printf("\nERROR: forbiden character: '%c'\n",c);
break;
}
switch (state)
{
case STATE_SEARCH_PARAM:
switch(ct)
{
case CHAR_SPACE:
continue;
case CHAR_EOL:
state = STATE_BREAK;
continue;
case CHAR_QMARK:
putchar('[');
state = STATE_IN_QUOT_PARAM;
continue;
default: //case CHAR_SYMBOL:
putchar('[');
putchar(c);
state = STATE_IN_PARAM;
}
continue;
case STATE_IN_PARAM:
switch (ct)
{
case CHAR_SYMBOL:
putchar(c);
continue;
case CHAR_SPACE:
puts("]");
state = STATE_SEARCH_PARAM;
continue;
case CHAR_EOL:
puts("]");
state = STATE_BREAK;
continue;
default: //case CHAR_QMARK:
printf("\nERROR: the quotation mark is not allowed in param!\n");
state = STATE_BREAK;
}
continue;
case STATE_IN_QUOT_PARAM:
switch (ct)
{
case CHAR_QMARK:
puts("]");
if (g_CharMap[*(p-2)]==CHAR_QMARK)
{
printf("\nERROR: empty param!\n");
state = STATE_BREAK;
continue;
}
state = STATE_OUT_QUOT_PARAM;
continue;
case CHAR_EOL:
printf("\nERROR: unexpected end of line!\n");
state = STATE_BREAK;
continue;
default:
putchar(c);
}
continue;
default: //case STATE_OUT_QUOT_PARAM:
switch (ct)
{
case CHAR_SPACE:
state = STATE_SEARCH_PARAM;
continue;
case CHAR_EOL:
state = STATE_BREAK;
continue;
default:
printf("\nERROR: missing space between params!\n");
state = STATE_BREAK;
}
continue;
}
}
return 0;
}
void InitCharMap()
{
g_CharMap[0] = CHAR_EOL;
g_CharMap[0xA] = CHAR_EOL;
g_CharMap[0xD] = CHAR_EOL;
g_CharMap[9] = CHAR_SPACE;
g_CharMap[0x20] = CHAR_SPACE;
g_CharMap['"'] = CHAR_QMARK;
for (char i=0x30; i<=0x39; ++i) g_CharMap[i] = CHAR_SYMBOL;
for (char i='A'; i<='Z'; ++i) g_CharMap[i] = CHAR_SYMBOL;
for (char i='a'; i<='z'; ++i) g_CharMap[i] = CHAR_SYMBOL;
}


