【问题标题】:Inventory Restock with MATLAB (Low-Level I/O)使用 MATLAB 进行库存补货(低级 I/O)
【发布时间】:2014-10-15 14:24:29
【问题描述】:

又是 I/O 让我感到困惑的时候。在这种情况下,我的目标是编写一个函数,该函数接收一个 .txt 库存项目文件和另一个 .txt 价格文件,并输出补货的总成本,以及一个包含原始库存的 .txt 文件数据和需要补货的物品数量。例如:

Inventory Data:

Buns #50 #63
Burgers #32 #55
Ketchup #6 #10
Hotdogs #4 #35
Mustard #7 #8

注意:标头包含在 .txt 文件中,并且总会有五件商品需要补货

我的输出文件应该是:

Inventory Data:

Buns #50 #63
Burgers #32 #55
Ketchup #6 #10
Hotdogs #4 #35
Mustard #7 #8


Restocking Data:

Buns #63 #13
Burgers #55 #23
Ketchup #10 #4
Hotdogs #35 #31
Mustard #8 #1

我的输出总数应该是 271,因为

Prices:

Buns $2
Burgers $5
Ketchup $1
Hotdogs $4
Mustard $2

Amro 很友善地帮助我弄清楚如何提取我需要的线条,以及如何从我拥有的东西中减去我的需要。现在我的最后一个斗争(也是我在更好地个性化问题之前需要克服的最后一个障碍)是弄清楚如何编写一个输出原始数据以及补充数据的最终数据。它必须看起来像测试用例

 function[restock_cost] = inventory2(file, prices)

%// Reads both files
fh = fopen(file, 'rt');
C = textscan(fh, '%s', 'Delimiter','');
inventory = C{1};
fclose(fh);
Original = C{:};
Original = char(Original);

fh2 = fopen(prices, 'rt');
D = textscan(fh2, '%s', 'Delimiter','');
prices = D{1};
fclose(fh2);

%// Breaks up inventory data
inventory(1) = [];
x = regexp(inventory, '(\w+) #(\d+) #(\d+)', 'tokens', 'once');
x = vertcat(x{:});
itemName = x(:,1);
itemHave = str2double(x(:,2));
itemNeeded = str2double(x(:,3));
itemName = char(itemName);


%// Determines what needs to be restocked and how much is needed
Restock = itemNeeded - itemHave;

%// Breaks up price info
prices(1) = [];
x = regexp(prices, '(\w+) \$(\d+)', 'tokens', 'once');
x = vertcat(x{:});
item = x(:,1);
prices = str2double(x(:,2));

%// Finds the price
restock_cost = sum((Restock .* prices));

%// gets the business name
[name, ~] = strtok(file,'_');

%// Finds the size of Original(may help)
[r,c] = size(Original);
[r2,c2] = size(itemName);
[r3,c3] = size(itemNeeded);

%// Starts to write my output file.
fh2 = fopen([name '_RestockingData.txt'], 'wt');
fprintf(fh2, 'Inventory Data: \n');
fprintf(fh2, '\n');

for i = 2:r %// Don't want the header included
    fprintf(fh2, Original(i,1:c));
    fprintf(fh2,'\n');
end
fprintf(fh2, '\n');
fprintf(fh2,'\n');
fprintf(fh2, 'Restocking Data: \n');
fprintf(fh2,'\n');

for j = 1:r2
    fprintf(fh2, itemName(j,1:c2));
    fprintf(fh2,' #%d ', itemNeeded(j));
    fprintf(fh2, '#%d', Restock(j));
    fprintf(fh2,'\n');
end

end

这很接近,但我需要它来输出进货数据,在项目名称和数字之间只有一个空格。相反,它给了我:

Inventory Data: 

Chips #40 #100    
Lettuce #80 #90   
Cheese #22 #60    
Tortillas #65 #100
Tomatoes #40 #70  



Restocking Data: 

Chips     #100 #60
Lettuce   #90 #10
Cheese    #60 #38
Tortillas #100 #35
Tomatoes  #70 #30

我也试过这个:

Restock_Data = {};
Restock_Data = [Restock_Data, {itemName, itemNeeded, Restock}];
Restocking = {Restock_Data};
Kill_Cell = [{Restocking}];

for j = 1:r2

    fprintf(fh2, Restock_Data(j));
    fprintf(fh2,'\n');
end

我需要将我的单元格转换为其他形式,但索引它(正如您在 Kill_Cell 中看到的那样)不起作用。 结束

这应该就是一切。以下是给我的笔记,以防万一:

Notes: 
   - All inventory numbers will have a # in front of them 
   - All the prices will have a $ in front of them and will always be a
     full dollar amount.
   - When creating the new output every item should be seperated by a space
       Ex. 'Chips #5 #2'
   - There will always be 5 items to stock.
   - If your output file is not EXACTLY the same as the solution txt file,
     then you will receive 0 credit for it.

【问题讨论】:

  • 你熟悉textscan函数吗?这可能是最适合您需求的一种。还是应该使用较低级别的函数?
  • 我尝试使用 textscan,但我不太清楚如何正确使用它。我们不一定被教过 textscan,但它在书中。只是没有很好地解释。

标签: matlab if-statement file-io while-loop low-level-io


【解决方案1】:

这是使用 textscan 读取库存文件的一种方法:

fid = fopen('inventory.txt', 'rt');
C = textscan(fid, '%s #%d #%d', 'HeaderLines',1, 'CollectOutput',true);
fclose(fid);

解析的数据:

>> C
C = 
    {5x1 cell}    [5x2 int32]

>> C{1}
ans = 
    'Buns'
    'Burgers'
    'Ketchup'
    'Hotdogs'
    'Mustard'

>> C{2}
ans =
          50          63
          32          55
           6          10
           4          35
           7           8

您也可以将文件简单地读取为字符串行的单元阵列(我在之前对您的问题的回答中使用过这个):

fid = fopen('inventory.txt', 'rt');
C = textscan(fid, '%s', 'Delimiter','');
C = C{1};
fclose(fid);

本例的结果:

>> C
C = 
    'Inventory Data:'
    'Buns #50 #63'
    'Burgers #32 #55'
    'Ketchup #6 #10'
    'Hotdogs #4 #35'
    'Mustard #7 #8'

编辑:

就像我展示的那样,首先我们将文件读取为字符串(文本行)的元胞数组:

% read both files
fid = fopen('inventory.txt', 'rt');
C = textscan(fid, '%s', 'Delimiter','');
inventory = C{1};
fclose(fid);

fid = fopen('prices.txt', 'rt');
C = textscan(fid, '%s', 'Delimiter','');
prices = C{1};
fclose(fid);

接下来我们使用正则表达式来匹配文本中的模式:

% parse inventory data
inventory(1) = [];
x = regexp(inventory, '(\w+) #(\d+) #(\d+)', 'tokens', 'once');
x = vertcat(x{:});
itemName = x(:,1)
itemHave = str2double(x(:,2))
itemNeeded = str2double(x(:,3))

% parse prices data
prices(1) = [];
x = regexp(prices, '(\w+) \$(\d+)', 'tokens', 'once');
x = vertcat(x{:});
item = x(:,1)
price = str2double(x(:,2))

最后,您可以应用您的逻辑来补充库存,并打印所需的输出...

【讨论】:

  • 这正是我即将编写的代码。你帮我省了麻烦。
  • 那么单元阵列组成中的 %s 是文件信息输入正确的地方吗?不是我,而是 MATLAB。然后我猜'分隔符'使它成为默认分隔符,所以我会说'/ n'?然后我不太确定 '' 位是干什么用的。填充一个空字符串还是什么?
  • @JessicaMarie: textscan 用于读取数据行。第二个参数是“格式说明符”,它告诉textscan 每行要读取多少个字段以及什么类型。通过指定'%s',我说我想读取一个字符串字段。最后一个选项 (delimiter='') 在这里是必需的,因为默认情况下,字段是用空格分隔的,并且通过指定一个空字符串 ('') 作为分隔符,该字段将有效地持续到行尾。因此,我们每行得到一整行。
  • textscan 是一个强大的功能,可以接受许多选项。有关所有详细信息,请参阅文档。它的文档长达几页,说明它有多复杂 :)
  • @JessicaMarie:应该始终使用最好的工具来完成这项工作,而对于这种文本处理,正则表达式真的非常灵活和强大......我很惊讶你还没有被介绍将正则表达式作为您的 uni 课程的一部分,看到您发布的大多数家庭作业问题都属于这种性质。
猜你喜欢
  • 1970-01-01
  • 2012-02-16
  • 1970-01-01
  • 2019-11-12
  • 1970-01-01
  • 2013-11-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多